├── .gitattributes ├── .github ├── PULL_REQUEST_TEMPLATE.md ├── actions │ └── setup-node │ │ └── action.yml ├── issue_template.md └── workflows │ ├── build.yaml │ ├── check_pull_requests.yaml │ ├── jest.yaml │ ├── markdownlint.yaml │ ├── prettier.yaml │ ├── textlint.yaml │ └── tsc.yaml ├── .gitignore ├── .husky └── pre-commit ├── .markdownlint.yaml ├── .markdownlintignore ├── .node-version ├── .nvmrc ├── .prettierignore ├── .prettierrc ├── .textlintrc ├── .vscode └── settings.json ├── .yarn ├── .gitattributes └── releases │ └── yarn-1.22.17.cjs ├── .yarnrc.yml ├── LICENSE-CC-BY-SA ├── LICENSE-MIT ├── README.md ├── babel.config.js ├── changelog.config.js ├── docs ├── README.md ├── about.md ├── how-to-use-typescript-playground.md ├── how-to-use-typescript-playground │ ├── image1.png │ ├── image2.png │ └── image3.png ├── icons │ ├── js.svg │ └── ts.svg ├── learning-resources.md ├── license.md ├── overview │ ├── README.md │ ├── before-typescript.md │ ├── ecmascript.md │ ├── ecosystem.md │ ├── features.md │ ├── javascript-is-typescript.md │ ├── range-of-typescript.md │ ├── static-type.md │ ├── typescript-is-not-that.md │ └── why-you-should-use-typescript.md ├── reference │ ├── README.md │ ├── advanced-topics │ │ ├── generator.md │ │ ├── getters-and-setters.md │ │ ├── project-references.md │ │ ├── tsconfig-for-dual-package-developers.md │ │ └── tsconfig-for-npm-package-developers.md │ ├── asynchronous │ │ ├── README.md │ │ ├── async.md │ │ ├── await.md │ │ └── promise.md │ ├── builtin-api │ │ ├── date.md │ │ ├── date │ │ │ ├── java-date.png │ │ │ └── mozilla-slide.png │ │ ├── error.md │ │ ├── map.md │ │ ├── regexp.md │ │ └── set.md │ ├── declaration-file.md │ ├── functions │ │ ├── arrow-functions.md │ │ ├── assertion-functions.md │ │ ├── callback-functions.md │ │ ├── default-parameters.md │ │ ├── destructuring-assignment-parameters.md │ │ ├── function-declaration-and-hoisting.md │ │ ├── function-declaration.md │ │ ├── function-expression-vs-arrow-functions.md │ │ ├── function-expression.md │ │ ├── function-is-a-value.md │ │ ├── function-is-an-object.md │ │ ├── function-parameters.md │ │ ├── function-type-declaration.md │ │ ├── iife.md │ │ ├── keyword-arguments-and-options-object-pattern.md │ │ ├── optional-parameters.md │ │ ├── overload-functions.md │ │ ├── pass-by-value.md │ │ ├── rest-parameters.md │ │ ├── this-parameters.md │ │ ├── type-guard-functions.md │ │ └── void-type.md │ ├── generics │ │ ├── README.md │ │ ├── built-in-libraries-using-generics.md │ │ ├── default-type-parameter.md │ │ ├── type-parameter-constraint.md │ │ ├── type-variables.md │ │ └── variance.md │ ├── import-export-require.md │ ├── jsx │ │ └── README.md │ ├── modules.md │ ├── object-oriented │ │ ├── class │ │ │ ├── README.md │ │ │ ├── abstract-class.md │ │ │ ├── access-modifiers.md │ │ │ ├── class-inheritance.md │ │ │ ├── class-is-an-object.md │ │ │ ├── class-nominality.md │ │ │ ├── constructor-shorthand.md │ │ │ ├── constructor.md │ │ │ ├── field-initializers.md │ │ │ ├── fields.md │ │ │ ├── final-sealed-class.md │ │ │ ├── instanceof-operator.md │ │ │ ├── methods.md │ │ │ ├── readonly-modifier-in-classes.md │ │ │ ├── return-this-type.md │ │ │ ├── static-fields.md │ │ │ └── static-methods.md │ │ ├── interface │ │ │ ├── README.md │ │ │ ├── implementing-interfaces.md │ │ │ ├── instanceof-and-interfaces.md │ │ │ ├── interface-inheritance.md │ │ │ ├── interface-vs-type-alias.md │ │ │ ├── open-ended-and-declaration-merging.md │ │ │ └── readonly-modifier-in-interfaces.md │ │ └── javascript-vs-typescript-in-oop-features.md │ ├── single-process-and-callback.md │ ├── statements │ │ ├── any-vs-unknown.md │ │ ├── control-flow-analysis-and-type-guard.md │ │ ├── exception.md │ │ ├── for-of.md │ │ ├── if-else.md │ │ ├── never.md │ │ ├── switch-and-variable-scope.md │ │ ├── switch-fallthrough.md │ │ ├── switch.md │ │ ├── ternary-operator.md │ │ ├── unknown.md │ │ └── variable-scope.md │ ├── tsconfig │ │ ├── alwaysstrict.md │ │ ├── exactoptionalpropertytypes.md │ │ ├── isolatedModules.md │ │ ├── nofallthroughcasesinswitch.md │ │ ├── noimplicitany.md │ │ ├── noimplicitoverride.md │ │ ├── noimplicitreturns.md │ │ ├── noimplicitthis.md │ │ ├── nopropertyaccessfromindexsignature.md │ │ ├── nouncheckedindexedaccess.md │ │ ├── nounusedlocals.md │ │ ├── nounusedparameters.md │ │ ├── option-list.md │ │ ├── strict.md │ │ ├── strictbindcallapply.md │ │ ├── strictfunctiontypes.md │ │ ├── strictnullchecks.md │ │ ├── strictpropertyinitialization.md │ │ ├── tsconfig.json-settings.md │ │ └── useunknownincatchvariables.md │ ├── type-reuse │ │ ├── README.md │ │ ├── conditional-types │ │ │ ├── README.md │ │ │ ├── distributive-conditional-types.md │ │ │ └── infer.md │ │ ├── indexed-access-types.md │ │ ├── keyof-type-operator.md │ │ ├── mapped-types.md │ │ ├── typeof-type-operator.md │ │ └── utility-types │ │ │ ├── awaited.md │ │ │ ├── exclude.md │ │ │ ├── extract.md │ │ │ ├── no-infer.md │ │ │ ├── nonnullable.md │ │ │ ├── omit.md │ │ │ ├── partial.md │ │ │ ├── pick.md │ │ │ ├── readonly.md │ │ │ ├── record.md │ │ │ ├── required.md │ │ │ └── return-type.md │ └── values-types-variables │ │ ├── any.md │ │ ├── array │ │ ├── array-as-a-object.md │ │ ├── array-literal.md │ │ ├── array-operations.md │ │ ├── array-type-is-covariant.md │ │ ├── destructuring-assignment-from-array.md │ │ ├── how-to-access-elements-in-an-array.md │ │ ├── how-to-loop-an-array.md │ │ ├── readonly-array.md │ │ ├── spread-syntax-for-array.md │ │ └── type-annotation-of-array.md │ │ ├── bigint.md │ │ ├── boolean.md │ │ ├── boxing.md │ │ ├── const-assertion.md │ │ ├── definite-assignment-assertion.md │ │ ├── difference-between-type-inference-and-dynamic-typing.md │ │ ├── discriminated-union.md │ │ ├── enum │ │ ├── README.md │ │ ├── enum-problems-and-alternatives-to-enums.md │ │ ├── numeric-enum.md │ │ └── string-enum.md │ │ ├── equality.md │ │ ├── intersection.md │ │ ├── let-and-const.md │ │ ├── literal-types.md │ │ ├── mental-model-of-types.md │ │ ├── null.md │ │ ├── number │ │ ├── README.md │ │ └── decimal-calculation-error.md │ │ ├── object │ │ ├── destructuring-assignment-from-objects.md │ │ ├── difference-among-object-and-object.md │ │ ├── difference-among-object-and-object │ │ │ └── image1.png │ │ ├── excess-property-checking.md │ │ ├── how-to-loop-an-object.md │ │ ├── index-signature.md │ │ ├── non-primitives-are-objects.md │ │ ├── object-literal.md │ │ ├── optional-chaining.md │ │ ├── optional-property.md │ │ ├── properties-of-objects.md │ │ ├── prototype-based-programming.md │ │ ├── readonly-property.md │ │ ├── readonly-vs-const.md │ │ ├── shorthand-property-names.md │ │ └── type-annotation-of-objects.md │ │ ├── primitive-types.md │ │ ├── satisfies.md │ │ ├── string.md │ │ ├── structural-subtyping.md │ │ ├── symbol.md │ │ ├── truthy-falsy-values.md │ │ ├── tuple.md │ │ ├── type-alias.md │ │ ├── type-annotation.md │ │ ├── type-assertion-as.md │ │ ├── type-coercion.md │ │ ├── type-inference.md │ │ ├── typeof-operator.md │ │ ├── undefined-vs-null.md │ │ ├── undefined.md │ │ ├── union.md │ │ └── vars-problems.md ├── symbols-and-keywords.md ├── tips │ ├── companion-object.md │ ├── generates-type-from-array.md │ ├── generates-type-from-object-key.md │ ├── generates-type-from-object-property.md │ ├── generates-type-from-object.md │ ├── generates-type-of-element-from-array.md │ ├── get-a-subset-of-an-object.md │ ├── merge-objects.md │ ├── receive-an-object-return-an-object.md │ └── shallow-copy-object.md ├── tutorials │ ├── README.md │ ├── component-test.md │ ├── component-test │ │ ├── result_fail.png │ │ ├── result_pass.png │ │ ├── result_pass2.png │ │ └── simpleButton.gif │ ├── eslint.md │ ├── husky.md │ ├── jest.md │ ├── make-a-simple-function-via-cli.md │ ├── nextjs.md │ ├── prettier.md │ ├── react-like-button-tutorial.md │ ├── react-like-button-tutorial │ │ ├── like1.png │ │ ├── like2.gif │ │ ├── screen1.png │ │ ├── screen2.png │ │ ├── screen3.png │ │ └── screen4.png │ ├── setup.md │ ├── vercel-deploy.md │ └── vercel-deploy │ │ ├── random-cat-preview-one-more-cat.png │ │ ├── vercel-dashboard-production-random-cat.png │ │ ├── vercel-deploy-complete-random-cat.png │ │ ├── vercel-github-checks-merge-ready.png │ │ ├── vercel-github-pr-preview-comment.png │ │ ├── vercel-import-github-random-cat.png │ │ ├── vercel-project-delete-confirmation.png │ │ ├── vercel-project-settings-delete-random-cat.png │ │ └── vercel-project-settings-random-cat.png ├── typescript.md └── writing │ ├── contributing.md │ ├── file-structure.md │ ├── getting-started.md │ ├── how-to-change.md │ ├── japanese-english-table.md │ ├── markdown.md │ ├── pdr │ ├── 0000-why-do-we-write-technical-books.md │ ├── 0001-write-with-gitbook.md │ ├── 0002-iterative-writing-process.md │ ├── 0002-iterative-writing-process │ │ └── iterative-vs-incremental.jpg │ ├── 0003-target-readers.md │ ├── 0004-how-to-manage-article-status.md │ ├── 0005-about-license.md │ ├── 0006-use-desu-masu.md │ ├── 0007-use-function-for-sample-code.md │ ├── 0008-prefer-type-alias-over-interface.md │ ├── 0009-use-docusaurus.md │ ├── 0010-ticket-driven.md │ ├── README.md │ └── pdr-template.md │ ├── styles.md │ ├── ticket-driven.md │ ├── vscode.md │ └── writing.md ├── docusaurus.config.js ├── flake.lock ├── flake.nix ├── gpts ├── README.md ├── create-knowledge.ts ├── docs.json └── prompt.txt ├── jest.config.js ├── lint-staged.config.js ├── package.json ├── prh ├── README.md ├── js-primer.yml └── yytypescript.yml ├── sidebars.js ├── src ├── components │ ├── codeReadingAssistant │ │ ├── README.md │ │ ├── docusaurusPlugin.js │ │ ├── index.module.css │ │ ├── index.tsx │ │ ├── model │ │ │ ├── findByPoint.test.ts │ │ │ ├── findByPoint.ts │ │ │ ├── index.ts │ │ │ ├── nodeUtils.ts │ │ │ ├── print.ts │ │ │ ├── topics.ts │ │ │ └── transforms │ │ │ │ ├── asExpression.ts │ │ │ │ ├── asKeyword.ts │ │ │ │ ├── asteriskToken.test.ts │ │ │ │ ├── asteriskToken.ts │ │ │ │ ├── defaultTransform.ts │ │ │ │ ├── equalsGreaterThanToken.test.ts │ │ │ │ ├── equalsGreaterThanToken.ts │ │ │ │ ├── exclamationToken.test.ts │ │ │ │ ├── exclamationToken.ts │ │ │ │ ├── heritageClause.ts │ │ │ │ ├── index.ts │ │ │ │ ├── mappedType.test.ts │ │ │ │ ├── mappedType.ts │ │ │ │ ├── minusToken.test.ts │ │ │ │ ├── minusToken.ts │ │ │ │ ├── nullKeyword.test.ts │ │ │ │ ├── nullKeyword.ts │ │ │ │ ├── parameter.test.ts │ │ │ │ ├── parameter.ts │ │ │ │ ├── plusToken.test.ts │ │ │ │ ├── plusToken.ts │ │ │ │ ├── questionToken.test.ts │ │ │ │ ├── questionToken.ts │ │ │ │ ├── typeOperator.test.ts │ │ │ │ ├── typeOperator.ts │ │ │ │ ├── utils.ts │ │ │ │ ├── variableDeclaration.test.ts │ │ │ │ ├── variableDeclaration.ts │ │ │ │ ├── variableDeclarationList.test.ts │ │ │ │ └── variableDeclarationList.ts │ │ ├── sampleCodes │ │ │ ├── sampleCode1.tsx │ │ │ └── tsconfig.json │ │ └── useStore.ts │ ├── icons │ │ └── Bot.tsx │ ├── ogpImage.ts │ ├── pageRef │ │ ├── pageRef.tsx │ │ └── pageRefRemark.js │ ├── postILearned │ │ ├── postILearned.tsx │ │ └── postILearnedRemark.js │ ├── questionAndReportIssue.tsx │ ├── useDoc.ts │ └── useIsDarkMode.ts ├── css │ └── custom.css ├── pages │ ├── code-reading-assistant.module.css │ └── code-reading-assistant.tsx └── theme │ ├── DocItem │ └── Metadata │ │ └── index.tsx │ ├── EditThisPage │ └── index.tsx │ └── NavbarItem │ └── HtmlNavbarItem │ └── index.tsx ├── static ├── .nojekyll ├── img │ ├── browser-rendering-engine-javascript-engine-ecmascript-relations.eps │ ├── difference-among-object-and-object.png │ ├── how-to-loop-an-array.png │ ├── js.svg │ ├── logo.svg │ ├── ogp.ai │ ├── ogp.png │ ├── overview │ │ └── ecmascript │ │ │ └── browser-rendering-engine-javascript-engine-ecmascript-relations.svg │ ├── range-of-typescript.png │ ├── reference │ │ └── values-types-variables │ │ │ └── structural-subtyping │ │ │ └── class-diagram-shape-circle-rectangle.svg │ ├── strictNullChecks.png │ ├── ts.svg │ ├── tutorial │ │ ├── docsVersionDropdown.png │ │ ├── eslint │ │ │ ├── error-meaning.ai │ │ │ ├── error-meaning.svg │ │ │ ├── string-quotes-chart.ai │ │ │ ├── string-quotes-chart.svg │ │ │ ├── terminal-npx-eslint-src-airbnb-with-rules.ai │ │ │ ├── terminal-npx-eslint-src-airbnb-with-rules.svg │ │ │ ├── terminal-npx-eslint-src-airbnb.ai │ │ │ ├── terminal-npx-eslint-src-airbnb.svg │ │ │ ├── terminal-npx-eslint-src-semi.ai │ │ │ ├── terminal-npx-eslint-src-semi.svg │ │ │ ├── terminal-npx-eslint-src-typescript.ai │ │ │ ├── terminal-npx-eslint-src-typescript.svg │ │ │ ├── terminal-npx-eslint-src.ai │ │ │ ├── terminal-npx-eslint-src.svg │ │ │ ├── vscode-eslint-example.png │ │ │ ├── vscode-marketplace.png │ │ │ ├── webstorm-eslint-config.png │ │ │ └── webstorm-eslint-example.png │ │ └── localeDropdown.png │ └── why-you-should-use-typescript.png ├── overview │ └── ecosystem │ │ ├── typescript-ecosystem-map.png │ │ └── typescript-ecosystem-map.svg ├── reference │ └── values-types-variables │ │ ├── discriminated-union │ │ ├── summary-card.png │ │ ├── summary-card@2x.png │ │ └── summary-card@3x.png │ │ └── mental-model-of-types │ │ ├── 2way-views-types.svg │ │ ├── subtyping-end-points.svg │ │ └── union-intersection-inclusion.svg ├── top │ ├── README.md │ ├── compile-error-feedback-on-editor.svg │ ├── compile-from-typescript-to-javascript.svg │ ├── type-annotation.svg │ ├── type-inference.svg │ └── typescript-as-superset-of-javascript.svg └── tutorials │ ├── jest │ ├── check-jest-works.svg │ ├── yarn-jest-isZero-1.svg │ └── yarn-jest-isZero-2.svg │ └── nextjs │ ├── nextjs-cat-image-display-result.png │ ├── nextjs-cat-image-generator-demo.mp4 │ ├── nextjs-cat-image-refresh-demo.mp4 │ ├── nextjs-cat-placeholder-console-log.png │ ├── nextjs-cat-placeholder-dark-mode.png │ ├── nextjs-initial-screen-dark-mode.png │ └── nextjs-styled-cat-image-page.png ├── tsconfig.json ├── tsconfig.twoslash.json ├── vercel.json └── yarn.lock /.gitattributes: -------------------------------------------------------------------------------- 1 | *.ai -diff 2 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | close # 9 | -------------------------------------------------------------------------------- /.github/actions/setup-node/action.yml: -------------------------------------------------------------------------------- 1 | name: 'Setup Node' 2 | description: 'Set up GitHub Actions workflow with a specific version of node.js' 3 | 4 | runs: 5 | using: 'composite' 6 | steps: 7 | - uses: actions/setup-node@v4 8 | with: 9 | node-version: 20 -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | ## 何をどうしたいか? 2 | 3 | ## そうしたい理由は何か?(誤植の修正など理由が自明な場合は不要) 4 | 5 | ## 着手可能になったら自分でプルリクエストを作成したいか? 6 | 自分で作成したい or 他の人でも可 7 | 8 | ※ 着手可になってから、1ヶ月以上経過している場合は他の人が着手する可能性があります。 9 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: build 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | branches: 8 | - master 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Setup Node 15 | uses: "./.github/actions/setup-node" 16 | - run: yarn --frozen-lockfile 17 | - run: yarn build 18 | -------------------------------------------------------------------------------- /.github/workflows/check_pull_requests.yaml: -------------------------------------------------------------------------------- 1 | name: check_pull_requests 2 | on: 3 | pull_request_target: 4 | types: [opened, edited, reopened, synchronize] 5 | jobs: 6 | check_pull_requests: 7 | runs-on: ubuntu-latest 8 | permissions: 9 | issues: read 10 | pull-requests: write 11 | steps: 12 | - uses: nearform-actions/github-action-check-linked-issues@v1 13 | with: 14 | exclude-branches: "release/**, dependabot/**" 15 | custom-body-comment: |- 16 | プルリクエスト本文中に関連するissueが見つかりませんでした。[チケット駆動のルール](https://typescriptbook.jp/writing/ticket-driven)に基づき、[キーワードを用いたissueの関連付け機能](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword)をご利用ください。 17 | -------------------------------------------------------------------------------- /.github/workflows/jest.yaml: -------------------------------------------------------------------------------- 1 | name: jest 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | branches: 8 | - master 9 | jobs: 10 | jest: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Setup Node 15 | uses: "./.github/actions/setup-node" 16 | - run: yarn --frozen-lockfile 17 | - run: yarn test 18 | -------------------------------------------------------------------------------- /.github/workflows/markdownlint.yaml: -------------------------------------------------------------------------------- 1 | name: markdownlint 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | branches: 8 | - master 9 | jobs: 10 | markdownlint: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Setup Node 15 | uses: "./.github/actions/setup-node" 16 | - run: yarn --frozen-lockfile 17 | - run: yarn markdownlint 18 | -------------------------------------------------------------------------------- /.github/workflows/prettier.yaml: -------------------------------------------------------------------------------- 1 | name: prettier 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | branches: 8 | - master 9 | jobs: 10 | prettier: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Setup Node 15 | uses: "./.github/actions/setup-node" 16 | - run: yarn --frozen-lockfile 17 | - run: yarn prettier 18 | -------------------------------------------------------------------------------- /.github/workflows/textlint.yaml: -------------------------------------------------------------------------------- 1 | name: textlint 2 | on: [pull_request] 3 | jobs: 4 | textlint: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v1 8 | - uses: reviewdog/action-setup@v1 9 | - run: reviewdog -version 10 | - run: npm install --ignore-scripts 11 | - run: | 12 | npx textlint -f checkstyle 'docs/**/*.md' \ 13 | | reviewdog -f=checkstyle -name="textlint" -reporter=github-pr-review 14 | env: 15 | REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} 16 | -------------------------------------------------------------------------------- /.github/workflows/tsc.yaml: -------------------------------------------------------------------------------- 1 | name: tsc 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | branches: 8 | - master 9 | jobs: 10 | tsc: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Setup Node 15 | uses: "./.github/actions/setup-node" 16 | - run: yarn --frozen-lockfile 17 | - run: yarn typecheck 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | /.cache 11 | 12 | # Misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | 23 | # JetBrains IDE 24 | /.idea 25 | 26 | # yarn 27 | /.yarn/* 28 | !/.yarn/patches 29 | !/.yarn/plugins 30 | !/.yarn/releases 31 | !/.yarn/sdks 32 | /.pnp.* 33 | .vercel 34 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn lint-staged 5 | 6 | -------------------------------------------------------------------------------- /.markdownlint.yaml: -------------------------------------------------------------------------------- 1 | default: true 2 | line-length: false 3 | no-bare-urls: false 4 | no-alt-text: false 5 | ul-style: 6 | style: dash 7 | heading-style: 8 | style: atx 9 | ul-indent: 10 | indent: 2 11 | no-inline-html: false # JSXに反応してしまうのでfalse 12 | -------------------------------------------------------------------------------- /.markdownlintignore: -------------------------------------------------------------------------------- 1 | .github/PULL_REQUEST_TEMPLATE.md 2 | .github/issue_template.md 3 | 4 | node_modules 5 | 6 | # 7 | # IDEs & editors 8 | # 9 | /.idea 10 | 11 | # 12 | # Generated files 13 | # 14 | /CHANGELOG.md 15 | /pnpm-lock.yaml 16 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | .nvmrc -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v20.10.0 -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .github/issue_template.md 2 | 3 | # 4 | # IDEs & editors 5 | # 6 | /.idea 7 | 8 | # 9 | # Generated files 10 | # 11 | /.docusaurus 12 | /build 13 | pnpm-lock.yaml 14 | /.cache 15 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "overrides": [ 3 | { 4 | "files": ["*.md"], 5 | "options": { 6 | "parser": "markdown-nocjsp" 7 | } 8 | } 9 | ], 10 | "plugins": ["prettier-plugin-md-nocjsp"] 11 | } 12 | -------------------------------------------------------------------------------- /.textlintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "prh": { 4 | "rulePaths": [ 5 | "./prh/js-primer.yml", 6 | "./prh/yytypescript.yml" 7 | ] 8 | } 9 | }, 10 | "filters": { 11 | "comments": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": [ 3 | "bivariance", 4 | "camelcase", 5 | "contravariance", 6 | "Deno", 7 | "instanceof", 8 | "keyof", 9 | "mkdir", 10 | "nounusedlocals", 11 | "twoslash", 12 | "typeof", 13 | "WHATWG" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /.yarn/.gitattributes: -------------------------------------------------------------------------------- 1 | # To prevent showing massive diffs when each time you subsequently add or update them 2 | /releases/** binary 3 | /plugins/** binary 4 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | yarnPath: .yarn/releases/yarn-1.22.17.cjs 2 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 YYTypeScript 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # サバイバルTypeScript 2 | 3 | TypeScriptの入門書です。 4 | 5 | https://typescriptbook.jp/ 6 | 7 | ## 特徴 8 | 9 | ### 実務指向 10 | 11 | 「TypeScriptを最短ルートで実務で使えるように読者を導く」を目標に、実務で必須な知識に厳選した内容になっています。実務利用が希なTypeScript機能は、過学習になるため意図的に省いています。逆に、TypeScript範囲外のことでも実務利用が頻繁な知識はふんだんに盛り込んでいます。 12 | 13 | ### 自然な学習の流れ 14 | 15 | まず、プログラマーの言語学習の自然な流れを意識した章立てになっています。次の順で章立てされているため、ストレス少なめで学習していけます。 16 | 17 | 1. あらまし: TypeScriptがどんなものか概要を知る 18 | 2. 作って学ぶ: TypeScriptで動くものを書いて、雰囲気をつかむ 19 | 3. 読んで学ぶ: TypeScriptの各言語機能を深堀りする 20 | 21 | 次に、TypeScriptを知るのに必須なJavaScriptの知識も並行して学べるようになっています。 22 | 23 | さらに、他言語での知識がTypeScript学習に活かせるよう工夫しています。TypeScript学習者の多くが他言語経験者です。Java、Python、PHP、Rubyなどの他言語と対比しながらTypeScriptを学べるようになっています。 24 | 25 | ### オープンソース 26 | 27 | 本書はオープンソースです。無料で読めるだけでなく、執筆にも携わることができます。 28 | 29 | ## 執筆に参加するには 30 | 31 | 執筆に参加する方法は次のページをご覧ください。 32 | 33 | https://typescriptbook.jp/writing 34 | 35 | ## コントリビューター 36 | 37 | 数々のPRありがとうございます! 38 | 39 | [![](https://contrib.rocks/image?repo=yytypescript/book)](https://github.com/yytypescript/book/graphs/contributors) 40 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve("@docusaurus/core/lib/babel/preset")], 3 | }; 4 | -------------------------------------------------------------------------------- /changelog.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | closedIssueMessage: "Close ", 3 | closedIssuePrefix: "", 4 | }; 5 | -------------------------------------------------------------------------------- /docs/how-to-use-typescript-playground/image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/how-to-use-typescript-playground/image1.png -------------------------------------------------------------------------------- /docs/how-to-use-typescript-playground/image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/how-to-use-typescript-playground/image2.png -------------------------------------------------------------------------------- /docs/how-to-use-typescript-playground/image3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/how-to-use-typescript-playground/image3.png -------------------------------------------------------------------------------- /docs/icons/js.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/icons/ts.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/overview/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: /overview 3 | --- 4 | 5 | # TypeScriptのあらまし 6 | 7 | 本章では、TypeScriptの概要について触れます。同時に、TypeScriptの良さや、TypeScriptがJavaScriptエコシステムでどういった立ち位置にあるのかを示すことで、全体像を知っていただきます。 8 | 9 | TypeScriptとは何なのか詳しく知ってもらったり、読者が同僚や属するチームにTypeScriptをPRできるような情報を提供します。TypeScriptの歴史、思想、哲学を知ってもらうことで、どのようなところでTypeScriptがその本領を発揮するのかを学びます。TypeScriptをなぜ使うべきなのか?TypeScriptのアドバンテージは何なのか?逆に、TypeScriptが向かないところはどこなのか?TypeScriptとJavaScriptはどのような関係なのか?といった疑問に答えていきます。 10 | -------------------------------------------------------------------------------- /docs/overview/javascript-is-typescript.md: -------------------------------------------------------------------------------- 1 | # JavaScriptはTypeScriptの一部 2 | 3 | TypeScriptの文法はJavaScriptの文法を拡張したものです。TypeScriptで拡張された文法は、主に型に関する部分です。それ以外のほとんどの文法はJavaScriptに由来するものです。そのため、素のJavaScriptもTypeScriptとして扱うことができます。たとえば、次のコードは100%JavaScriptのものですが、これをTypeScriptコンパイラーは解析でき、静的な検査が行なえます。 4 | 5 | ```js twoslash 6 | const hello = "Hello"; 7 | const world = "World"; 8 | console.log(hello + " " + world); 9 | // @log: "Hello World" 10 | ``` 11 | 12 | TypeScriptから見ると、JavaScriptはTypeScriptの一部と言えます。そのため、TypeScriptを十分に理解するには、JavaScriptの理解が欠かせません。まだJavaScriptをよく分かっていない場合は、TypeScriptの学習と平行してJavaScriptも学ぶ必要があります。本書はTypeScript入門者向けですが、TypeScriptの理解に欠かせないJavaScriptの文法や仕様についても同時に学べるようになっています。 13 | -------------------------------------------------------------------------------- /docs/reference/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: /reference 3 | --- 4 | 5 | # 読んで学ぶTypeScript 6 | 7 | 本章では、TypeScriptの言語機能をひとつひとつ解説します。解説の範囲はTypeScriptに留まらず、JavaScriptについても必要なものを解説します。これは、TypeScript学習者がJavaScriptも並行して学ぶことが多いためです。 8 | 9 | どの機能がTypeScriptのものか、JavaScriptのものかがわかるように配慮しています。JavaScriptの機能については「JavaScriptの〜は」などと、TypeScriptの機能については「TypeScriptの〜は」などのように言語名を文中に記すようにしています。言語名が随所に出てくるため、読んでいてくどいと思われるかもしれませんが、どの機能がどちらの言語のものかを明確に理解しておくことは重要なので、ご辛抱いただければ幸いです。 10 | 11 | 本章の流れは、コード上の小さいパーツから大きいパーツに行くように構成しています。値や変数から始まり、文、関数、そしてクラスなどのオブジェクト指向プログラミング要素、さらにモジュールといったように、読み進めるにしたがって粒度の大きい要素についての話になっていきます。 12 | -------------------------------------------------------------------------------- /docs/reference/advanced-topics/generator.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: ジェネレーター 3 | --- 4 | 5 | # ジェネレーター (generator) 6 | 7 | Generatorを使用した関数はアロー関数での表記ではなく、必ず`function*() {}`と書く必要があります。次は可能なGeneratorの記述方法です。 8 | 9 | ```ts twoslash 10 | function* generatorFunction1() { 11 | // ... 12 | } 13 | 14 | const generatorFunction2 = function* () { 15 | // ... 16 | }; 17 | 18 | class GeneratorSample { 19 | public *generatorFunction3() { 20 | // ... 21 | } 22 | } 23 | ``` 24 | 25 | Generatorは反復可能(`Iterable`)な反復子(`Iterator`)であるインターフェース`IterableIterator`を実装したクラスのオブジェクトのことです。条件を満たしたクラスはGenerator関数の中で`yield`キーワードを使えます。`yield`は呼ばれたときに一度その値を呼び出し元へ返却し、次に呼ばれたときはその続きから処理を開始します。 26 | 27 | `Promise`が一般化する以前、非同期処理を代わりに担当する目的でGeneratorが使われていたことはありますが、前述の`Promise`に加えて`async / await`が一般的に使われるようになってから非同期処理の目的でGeneratorを使う機会は減りました。現在でも大量のデータを取得したいときに一度ではなく、小出しに取得したいときにGeneratorは使い道があります。 28 | -------------------------------------------------------------------------------- /docs/reference/advanced-topics/getters-and-setters.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: セッターとゲッター 3 | --- 4 | 5 | # セッターとゲッター (set, get) 6 | 7 | プロパティへのインターセプター(参照・代入・監視などの意味)としGetter/Setterがあります。 8 | 9 | 記述方法のサンプルは次のようになります。 10 | 11 | ```ts twoslash 12 | class Human { 13 | private _name: string; 14 | 15 | public constructor(name: string) { 16 | this._name = name; 17 | } 18 | 19 | // Getter宣言 20 | get name(): string { 21 | return this._name; 22 | } 23 | 24 | // Setter宣言 25 | set name(name: string) { 26 | this._name = name; 27 | } 28 | } 29 | 30 | const human = new Human(""); 31 | // Setterを利用 32 | human.name = `田中太郎`; 33 | // Getterを利用 34 | console.log(human.name); 35 | // @log: 田中太郎 36 | ``` 37 | 38 | メソッドと違い、getter/setterを呼ぶ場合は`()`は不要です。 39 | 40 | ```ts twoslash 41 | class Human { 42 | private _name: string; 43 | 44 | public constructor(name: string) { 45 | this._name = name; 46 | } 47 | 48 | get name(): string { 49 | return this._name; 50 | } 51 | 52 | set name(name: string) { 53 | this._name = name; 54 | } 55 | } 56 | 57 | const human = new Human("田中太郎"); 58 | // ---cut--- 59 | // @errors: 2349 6234 60 | // Getter 61 | console.log(human.name); // 正しいGetterの使用方法 62 | // @log: "田中太郎" 63 | console.log(human.name()); // エラー :human.name is not a function 64 | 65 | // Setter 66 | human.name = "田中太郎"; // 正しいSetterの使用方法 67 | human.name("田中太郎"); 68 | ``` 69 | 70 | ## Getter 71 | 72 | Getterの記述方法を日本語で表すと次のようになります。 73 | 74 | ```ts 75 | get 名前(): 型 { 76 | 必要ならば処理(); 77 | return 戻り値; 78 | } 79 | ``` 80 | 81 | Getterに引数を指定することはできません。また戻り値を必ず指定する必要があります。 82 | 83 | ## Setter 84 | 85 | Setterの記述方法を日本語で表すと次のようになります。 86 | 87 | ```ts 88 | set 名前(変数 : 型) { 89 | 必要ならば処理(); 90 | 保存処理(); 91 | } 92 | ``` 93 | 94 | 引数が必ずひとつ必要です。また戻り値を指定することはできません。 95 | -------------------------------------------------------------------------------- /docs/reference/asynchronous/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 非同期処理 3 | slug: /reference/asynchronous 4 | --- 5 | 6 | もしJavaScriptで本格的に何かを作りたいのであれば、非同期処理とは切っても切れない関係になるでしょう。初めのうちは理解に苦しむことが多いですが今では非同期処理を直観的に操作できる機能が実装されたのでハードルは大きく下がりました。 7 | 8 | ## JavaScriptにおける非同期処理 9 | 10 | JavaScriptはシングルプロセス、シングルスレッドで動作する言語です。この特徴については別のページにもありますが、これはすべてのプログラムは直列に処理されるということを意味します。 11 | 12 | [シングルプロセス・シングルスレッドとコールバック](../single-process-and-callback.md) 13 | 14 | これだけ聞けばすべてのJavaScriptのプログラムは上から下に同期的に処理されるようにも聞こえます。 15 | ですがこの特徴には弱点があります。直列に処理されるため時間のかかる処理があるとその間は他の処理が実行されません。たとえばAPIリクエストの場合処理の大部分は待ち時間ですが、この待ち時間も直列に処理されるとその間は何もできないことになってしまいます。これをブロッキングといいます。 16 | この問題を回避するためにJavaScriptではノンブロッキングを扱います。ノンブロッキングでは処理を受けたあと即座に処理を返し、あとで別の方法で結果を伝えます。この方法をコールバックと呼ぶこともあります。コールバックの言葉は折り返しの電話を意味します。 17 | 18 | ## Promiseの誕生 19 | 20 | JavaScriptにおける非同期処理にはコードの見通しが悪くなる(コールバック地獄)という弊害があります。ES2015から追加されたPromiseはその打開策ともいえ、JavaScriptのコードをコールバック地獄から解き放ちました。 21 | そしてそのPromiseをさらに使いやすくするためにasync/awaitがES2017で追加されました。 22 | 23 | ## 本章で取り上げる内容について 24 | 25 | 本章ではこれらPromise/async/awaitの使いかたや特徴をそれぞれのページに分けて取り上げていきます。 26 | -------------------------------------------------------------------------------- /docs/reference/builtin-api/date/java-date.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/reference/builtin-api/date/java-date.png -------------------------------------------------------------------------------- /docs/reference/builtin-api/date/mozilla-slide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/reference/builtin-api/date/mozilla-slide.png -------------------------------------------------------------------------------- /docs/reference/builtin-api/error.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Error 3 | --- 4 | 5 | `Error`はJavaScriptの組み込みAPIのひとつで例外を取り扱うためのオブジェクトです。 6 | 7 | ## Errorオブジェクトの作り方 8 | 9 | `Error`オブジェクトを作るには`Error`クラスを`new`します。例外を投げるためには`throw`を使います。 10 | 11 | ```ts twoslash 12 | throw new Error(); 13 | ``` 14 | 15 | ## JavaScriptではErrorクラス以外も例外としてthrowできる 16 | 17 | とはいえ、JavaScriptでは例外を表す`Error`クラスとそのサブクラスだけを`throw`できるのではなく、どのような値も`throw`できます。 18 | 19 | ```ts twoslash 20 | throw "id is not string!"; 21 | ``` 22 | 23 | ## Errorクラスのサブクラス 24 | 25 | 組み込みAPIとして`Error`には次のサブクラスがあります。 26 | 27 | - EvalError 28 | - InternalError 29 | - RangeError 30 | - ReferenceError 31 | - SyntaxError 32 | - TypeError 33 | - URIError 34 | 35 | また`Error`を拡張し独自のサブクラスを定義することもできます。 36 | 37 | ```ts twoslash 38 | class CustomeError extends Error { 39 | public constructor(message?: string) { 40 | super(message); 41 | } 42 | } 43 | 44 | const err: CustomeError = new CustomeError("FAILED!"); 45 | 46 | console.log(err.name); 47 | // @log: "Error" 48 | console.log(err.message); 49 | // @log: "FAILED!" 50 | console.log(err.stack); 51 | // @log: "Error: FAILED! ..." 52 | ``` 53 | 54 | ## 例外を捕捉する 55 | 56 | `throw`された例外は`catch`で捕捉できます。ですが先ほど述べたようにJavaScriptはどのような値も`throw`できるので`catch`した値の型は定まらず`any`型か`unknown`型として解釈されます。どちらの型になるかはtsconfig.jsonの`useUnknownInCatchVariables`の設定により決まります。 57 | 58 | [useunknownincatchvariables](../tsconfig/useunknownincatchvariables.md) 59 | 60 | もし捕捉した値があるクラスのインスタンスまたはある型であるかを判定したい場合は`instanceof`, `keyof`あるいは型ガードを使います。 61 | 62 | ```ts twoslash 63 | try { 64 | // ... 65 | } catch (e) { 66 | if (e instanceof Error) { 67 | // ... 68 | } 69 | } 70 | ``` 71 | -------------------------------------------------------------------------------- /docs/reference/functions/assertion-functions.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: アサーション関数 3 | --- 4 | 5 | # アサーション関数 (assertion functions) 6 | 7 | ユーザー定義の型ガード関数として使われるのはType predicateが主ですが、Assertion functionという方法もあります。 8 | Type predicateはboolean型の戻り値に対して使いましたがこちらは関数が例外を投げるかどうかで判定します。型ガード関数のページで作った関数`isDuck()`をAssertion functionsで書きかえると次のようになります。 9 | 10 | ```ts twoslash 11 | // @errors: 2339 12 | class Animal {} 13 | class Duck { 14 | public quacks(): void {} 15 | } 16 | declare function walksLikeDuck(animal: Animal): boolean; 17 | declare function quacksLikeDuck(animal: Animal): boolean; 18 | 19 | const animal = new Animal(); 20 | // ---cut--- 21 | function isDuck(animal: Animal): asserts animal is Duck { 22 | if (walksLikeDuck(animal)) { 23 | if (quacksLikeDuck(animal)) { 24 | return; 25 | } 26 | } 27 | 28 | throw new Error("YOU ARE A FROG!!!"); 29 | } 30 | 31 | // ここではquacks()は存在しない 32 | animal.quacks(); 33 | 34 | isDuck(animal); 35 | 36 | animal.quacks(); 37 | ``` 38 | 39 | こちらはこの関数が呼ばれた後であればいつでも変数`animal`は`Duck`型として解釈されます。 40 | -------------------------------------------------------------------------------- /docs/reference/functions/function-declaration-and-hoisting.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 関数宣言と巻き上げ 3 | --- 4 | 5 | # 関数宣言と巻き上げ (hoisting) 6 | 7 | JavaScriptの関数宣言と関数式の違いが現れるひとつの例は巻き上げ(hoisting)です。関数宣言には巻き上げがあり、関数式には巻き上げがありません。 8 | 9 | まずは関数宣言の例を見てみましょう。次のコードは、3行目に`hello`関数の関数宣言があります。そして、その宣言の前で`hello`関数を実行しています。 10 | 11 | ```js twoslash 12 | hello(); 13 | 14 | function hello() { 15 | console.log("Hello World"); 16 | } 17 | ``` 18 | 19 | このコードは、`hello`関数の定義行より前でその関数を呼び出しているのに、エラーにはならず問題なく"Hello World"が出力されます。これは関数宣言には巻き上げがあるためです。 20 | 21 | 次に関数式の例を見てみましょう。下のコードは`hello`関数を関数式を使って定義するようにしたものです。 22 | 23 | ```js twoslash 24 | hello(); 25 | 26 | const hello = function () { 27 | console.log("Hello World"); 28 | }; 29 | ``` 30 | 31 | このコードをJavaScriptとして実行してみると、1行目で「ReferenceError: Cannot access 'hello' before initialization」というエラーが起こります。関数式で関数を定義した場合は巻き上げがないため、このようなエラーが発生します。 32 | 33 | 以上のように、関数宣言と関数式には巻き上げの有無の違いがあります。関数式の場合は、関数定義と実行の順番を意識する必要が出てくるわけです。 34 | 35 | TypeScriptでは、定義前の関数式を呼び出そうとするとコンパイラーが指摘してくれます。 36 | 37 | ```ts twoslash 38 | hello(); 39 | // @errors: 2448 2454 40 | 41 | const hello = function () {}; 42 | ``` 43 | 44 | 関数宣言の場合は、JavaScriptと同じくエラーは発生しません。 45 | 46 | 巻き上げにより実行されるため、コンパイラーからの指摘はありません。 47 | 48 | ```ts 49 | hello(); // Hello World 50 | 51 | function hello() { 52 | console.log("Hello World"); 53 | } 54 | ``` 55 | -------------------------------------------------------------------------------- /docs/reference/functions/function-declaration.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 関数宣言 3 | --- 4 | 5 | # 関数宣言 (function declaration) 6 | 7 | 関数宣言はJavaScriptで関数を定義する構文です。 8 | 9 | ## 関数宣言構文 10 | 11 | JavaScriptの関数宣言はfunction構文を使います。 12 | 13 | ```js twoslash 14 | function hello() { 15 | return "hello"; 16 | } 17 | ``` 18 | 19 | ## 関数宣言構文の型注釈 20 | 21 | TypeScriptでは関数宣言の引数と戻り値に型注釈を書けます。 22 | 23 | ```ts twoslash 24 | function increment(num: number): number { 25 | return num + 1; 26 | } 27 | ``` 28 | 29 | 引数の型注釈を省略した場合、コンパイラーは`any`型と暗黙的に解釈します。 30 | 31 | ```ts twoslash 32 | // @noImplicitAny: false 33 | function increment(num): number { 34 | // ^? 35 | return num + 1; 36 | } 37 | ``` 38 | 39 | コンパイラーオプションの`noImplicitAny`を`true`に設定することで、引数の型注釈を必須にできます。 40 | 41 | ```ts twoslash 42 | // @noImplicitAny: true 43 | // @errors: 7006 44 | function increment(num): number { 45 | return num + 1; 46 | } 47 | ``` 48 | 49 | [noImplicitAny](../tsconfig/noimplicitany.md) 50 | 51 | 戻り値の型注釈を省略した場合、コンパイラーがコードから型推論します。 52 | 53 | ```ts twoslash 54 | function increment(num: number) { 55 | return num + 1; 56 | } 57 | const value = increment(1); 58 | // ^? 59 | ``` 60 | 61 | `return`が複数あり違う型を返している場合推論される型はユニオン型になります。 62 | 63 | ```ts twoslash 64 | function getFirst(items: number[]) { 65 | if (typeof items[0] === "number") { 66 | return items[0]; 67 | } 68 | return null; 69 | } 70 | 71 | getFirst([1, 2, 3]); 72 | // ^? 73 | ``` 74 | -------------------------------------------------------------------------------- /docs/reference/functions/function-is-a-value.md: -------------------------------------------------------------------------------- 1 | # 関数は値 2 | 3 | 他の言語では関数は特別な立ち位置のことがあります。ある言語では、同じ名前の変数を定義してもエラーにならないのに対し、同じ名前の関数定義はエラーになります。またある言語では、関数を変数に代入できなかったりします。 4 | 5 | JavaScriptの関数は値です。つまり、PHPのような他の言語と比べると特別扱いの度合いが少ないです。たとえば、関数を変数に代入することができます。 6 | 7 | ```js twoslash 8 | function hello() { 9 | return "Hello World"; 10 | } 11 | 12 | const helloWorld = hello; // 関数を変数に代入 13 | 14 | helloWorld(); // 関数呼び出しも問題なくできる 15 | ``` 16 | 17 | また、JavaScriptでは定義済みの関数と同じ名前の関数を宣言することができます。これはエラーにはなりません。これは実質、再代入のような振る舞いになります。 18 | 19 | ```js twoslash 20 | function hello() { 21 | return "HELLO"; 22 | } 23 | 24 | // これは二度目の関数宣言ですが、実質的には再代入です 25 | function hello() { 26 | return "KONNICHIWA"; 27 | } 28 | 29 | hello(); 30 | // @log: KONNICHIWA 31 | ``` 32 | 33 | このようにJavaScriptの関数は、booleanの値やstringの値などと同じような値としての性質があります。意図しない再代入はバグの原因になりますが、JavaScriptでは関数宣言では注意して書く以外に方法はありません。 34 | 35 | JavaScriptで関数の再代入によるバグを未然に回避したい場合は、`const`と関数式を組み合わせます。関数式については後述します。 36 | 37 | ```js twoslash 38 | const hello = function () { 39 | return "HELLO"; 40 | }; 41 | ``` 42 | 43 | ちなみに、TypeScriptではコンパイラーが重複した関数宣言を警告してくれるので、バグの心配はありません。 44 | 45 | ## 関数のスコープ 46 | 47 | 関数は値なので、関数名のスコープも変数と同じようにスコープの概念があります。たとえば、関数スコープの中で定義された関数は、そのローカルスコープでのみ使うことができます。 48 | 49 | ```js twoslash 50 | function main() { 51 | // ローカルスコープの関数 52 | function hello() { 53 | console.log("hello"); 54 | } 55 | 56 | hello(); 57 | } 58 | 59 | main(); 60 | // @log: "hello" 61 | 62 | // ローカルスコープで宣言された関数にはアクセスできない 63 | hello(); 64 | // @error: ReferenceError: hello is not defined 65 | ``` 66 | -------------------------------------------------------------------------------- /docs/reference/functions/function-is-an-object.md: -------------------------------------------------------------------------------- 1 | # 関数はオブジェクト 2 | 3 | JavaScriptの関数はオブジェクトです。したがって、関数にプロパティを持たせることができます。 4 | 5 | ```js twoslash 6 | function hello() { 7 | return "Hello World"; 8 | } 9 | 10 | hello.prop = 123; 11 | ``` 12 | -------------------------------------------------------------------------------- /docs/reference/object-oriented/class/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: クラス 3 | slug: /reference/object-oriented/class 4 | --- 5 | 6 | # クラス (class) 7 | 8 | クラスはオブジェクトの雛形を定義したもので、JavaScriptとTypeScriptでは`class`構文を用いてクラスが定義できます。 9 | 10 | ```ts twoslash 11 | class Person {} 12 | ``` 13 | 14 | クラスに対して`new`キーワードを使うと、オブジェクトを生成できます。 15 | 16 | ```ts twoslash 17 | class Person {} 18 | // ---cut--- 19 | const person = new Person(); 20 | ``` 21 | 22 | このように`class`でクラスを定義し、`new`でインスタンスを生成するスタイルは、JavaやPHP、Rubyなどと使用感がよく似ています。 23 | 24 | ## クラスの型注釈 25 | 26 | TypeScriptでは、クラスを定義するとクラス名と同じ名前の型が同時に定義されます。インスタンスを代入する変数に型注釈するには、クラス名を使います。 27 | 28 | ```ts twoslash 29 | class Person {} 30 | // ---cut--- 31 | const person: Person = new Person(); 32 | ``` 33 | -------------------------------------------------------------------------------- /docs/reference/object-oriented/class/class-inheritance.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: クラスの継承 3 | --- 4 | 5 | # クラスの継承 (inheritance) 6 | 7 | JavaScriptのクラスも他のクラスを持つ言語と同じように、`extends`キーワードで継承ができます。 8 | 9 | ```js twoslash 10 | class Parent {} 11 | class Child extends Parent {} 12 | ``` 13 | 14 | サブクラスにコンストラクタを書く場合、スーパークラスのコンストラクタは必ず呼び出す必要があります。スーパークラスのコンストラクタは`super()`で呼び出します。 15 | 16 | ```js twoslash 17 | class Parent {} 18 | class Child extends Parent { 19 | constructor() { 20 | super(); 21 | } 22 | } 23 | ``` 24 | -------------------------------------------------------------------------------- /docs/reference/object-oriented/class/class-is-an-object.md: -------------------------------------------------------------------------------- 1 | # クラスはオブジェクト 2 | 3 | JavaScriptのクラスの特徴は、クラスもオブジェクトの一種というところです。JavaScriptのオブジェクトはプロパティの集合体です。クラスもオブジェクトなのでプロパティの集合体としての性質を持ちます。したがって、定義したクラスはプロパティを追加したり、変更したりできます。 4 | 5 | ```js twoslash 6 | const myObject = {}; 7 | myObject.key = "value"; // プロパティを追加 8 | 9 | class MyClass {} 10 | MyClass.key = "value"; // プロパティを追加 11 | ``` 12 | 13 | 一方、TypeScriptでは型安全のためにこうした動的な拡張ができないようになっています。 14 | 15 | ```ts twoslash 16 | // @errors: 2339 17 | class MyClass {} 18 | MyClass.key = "value"; 19 | ``` 20 | -------------------------------------------------------------------------------- /docs/reference/object-oriented/class/class-nominality.md: -------------------------------------------------------------------------------- 1 | # 公称型クラス 2 | 3 | TypeScriptでは、クラスに1つでも非パブリックなプロパティがあると、そのクラスだけ構造的部分型ではなく公称型(nominal typing)になります。 4 | 5 | たとえば、`UserId`クラスと`GroupId`クラスで同名になってしまっている`id`プロパティをプライベートにするだけで、相互の代入が不可能になります。 6 | 7 | ```ts twoslash 8 | // @errors: 2322 9 | class UserId { 10 | private readonly id: string; 11 | 12 | constructor(id: string) { 13 | this.id = id; 14 | } 15 | } 16 | 17 | class GroupId { 18 | private readonly id: string; 19 | 20 | constructor(id: string) { 21 | this.id = id; 22 | } 23 | } 24 | 25 | const userId: UserId = new GroupId("..."); 26 | ``` 27 | 28 | この方法はフィールドに限らず、プライベートメソッドや`protected`プロパティでも同じ効果があります。 29 | 30 | ## 関連情報 31 | 32 | [構造的部分型 (structural subtyping)](../../values-types-variables/structural-subtyping.md) 33 | -------------------------------------------------------------------------------- /docs/reference/object-oriented/class/constructor.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: コンストラクタ 3 | --- 4 | 5 | # コンストラクタ (constructor) 6 | 7 | コンストラクタはクラスをnewしたときに実行される関数です。コンストラクタは、インスタンスプロパティの初期化する処理を実装する場所です。JavaScriptのコンストラクタは、constructor構文で書きます。 8 | 9 | ```ts 10 | class Person { 11 | constructor(name) { 12 | // ... 13 | } 14 | } 15 | ``` 16 | 17 | ## コンストラクタの型注釈 18 | 19 | TypeScriptでコンストラクタ引数の型注釈は、関数の型注釈のやり方と同じです。 20 | 21 | ```ts twoslash 22 | class Person { 23 | constructor(name: string) { 24 | // ... 25 | } 26 | } 27 | ``` 28 | 29 | コンストラクタの戻り値は型注釈できません。コンストラクタの戻り値は、当然クラスのインスタンスなので、型注釈でコンパイラーに教える必要性がないのです。 30 | 31 | ## コンストラクタに引数を渡す 32 | 33 | JavaScriptでコンストラクタに引数を渡す方法は、関数呼び出しの書き方とほぼ同じです。違いはnew演算子をつけることです。 34 | 35 | ```ts twoslash 36 | class Person { 37 | constructor(name: string) { 38 | // ... 39 | } 40 | } 41 | // ---cut--- 42 | new Person("Alice"); 43 | ``` 44 | 45 | ## コンストラクタを非同期化する 46 | 47 | TypeScriptでは、コンストラクタを非同期化することはできません。次のような書きかたをすることはできません。 48 | 49 | ```ts 50 | class Person { 51 | constructor(name: string) { 52 | // ... 53 | } 54 | } 55 | ``` 56 | 57 | どうしても非同期化したい場合は、クラスのインスタンスを返すファクトリーメソッドを用意して、そのメソッドの中で非同期処理を実行するようにします。 58 | 59 | ```ts 60 | class Person { 61 | static async create(name: string): Promise { 62 | // 非同期処理 63 | return new Person(name); 64 | } 65 | 66 | constructor(name: string) { 67 | // ... 68 | } 69 | } 70 | ``` 71 | 72 | ## 関連情報 73 | 74 | [constructor shorthand](constructor-shorthand.md) 75 | -------------------------------------------------------------------------------- /docs/reference/object-oriented/class/field-initializers.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: フィールドの初期化子 3 | --- 4 | 5 | # フィールドの初期化子 (initializer) 6 | 7 | TypeScriptでは、初期化子(initializer)を使うとインスタンスのフィールドの初期値を指定できます。初期化子はフィールド名の右に`= 値`と書きます。初期化子は、クラスがインスタンス化されるときに自動的に実行されます。 8 | 9 | ```ts twoslash 10 | class Point { 11 | x: number = 0; 12 | y: number = 0; 13 | } 14 | const point = new Point(); 15 | console.log(point.x, point.y); 16 | // @log: 0 0 17 | ``` 18 | 19 | 初期化子を用いた上の例は、次のコンストラクタでフィールドを初期化するのと同じ意味です。 20 | 21 | ```ts twoslash 22 | class Point { 23 | x: number; 24 | y: number; 25 | 26 | constructor() { 27 | this.x = 0; 28 | this.y = 0; 29 | } 30 | } 31 | ``` 32 | 33 | ## 初期化子と型推論 34 | 35 | 初期化子で値の型が自明な場合、TypeScriptコンパイラーはフィールドの型を推論してくれます。そのため、初期化子を伴うフィールドは型注釈を省略できます。 36 | 37 | ```ts twoslash 38 | class Point { 39 | x = 0; // number型と型推論される 40 | } 41 | ``` 42 | -------------------------------------------------------------------------------- /docs/reference/object-oriented/class/final-sealed-class.md: -------------------------------------------------------------------------------- 1 | # finalクラス・sealedクラス 2 | 3 | JavaやPHPなどの他の言語には、finalクラスという機能があります。finalクラスは継承できないクラスです。finalクラスは意図しないサブクラスが生まれるのを抑制できる機能です。こうした機能はJavaScriptにはありません。TypeScriptにもありません。同様にfinalメソッドもJavaScript、TypeScript両方にありません。 4 | 5 | sealedクラスはScalaやKotlinなどの言語に見られる機能で、継承を制限する面ではfinalクラスと似ています。sealedクラスは同じモジュール内(ファイルの単位など)であれば継承できますが、他のモジュールでは継承できないクラスです。sealedクラスのようなものは、JavaScriptにもTypeScriptにもありません。 6 | -------------------------------------------------------------------------------- /docs/reference/object-oriented/class/instanceof-operator.md: -------------------------------------------------------------------------------- 1 | # instanceof演算子 2 | 3 | `instanceof`演算子は、特定のオブジェクトがクラスのインスタンスかをチェックするJavaScriptの演算子です。 4 | 5 | ## 構文 6 | 7 | ```js twoslash 8 | // prettier-ignore 9 | オブジェクト instanceof クラス 10 | ``` 11 | 12 | ### 引数 13 | 14 | - オブジェクト: 検査するオブジェクトです。 15 | - クラス: 検査対象のクラス名です。 16 | 17 | ## 例 18 | 19 | ```ts twoslash 20 | class ClassA {} 21 | class ClassB {} 22 | const a = new ClassA(); 23 | console.log(a instanceof ClassA); 24 | // @log: true 25 | console.log(a instanceof ClassB); 26 | // @log: false 27 | ``` 28 | 29 | ## 継承と`instanceof` 30 | 31 | `instanceof`は継承関係をチェックすることもできます。たとえば、次のように`Child`クラスのインスタンスが`Parent`クラスのインスタンスかをチェックすることができます。 32 | 33 | ```ts twoslash 34 | class Parent {} 35 | class Child extends Parent {} 36 | const child = new Child(); 37 | console.log(child instanceof Parent); 38 | // @log: true 39 | ``` 40 | 41 | ## `instanceof`の反転 42 | 43 | `instanceof`演算子の結果を反転させる場合は、`値 instanceof クラス名`の句全体をカッコで囲った上で、否定演算子`!`を先頭につける必要があります。 44 | 45 | ```ts twoslash 46 | class MyClass {} 47 | const myInstance = new MyClass(); 48 | // ---cut--- 49 | if (!(myInstance instanceof MyClass)) { 50 | // myInstanceがMyClassではないときの処理 51 | } 52 | ``` 53 | 54 | ## 抽象クラスと`instanceof` 55 | 56 | TypeScriptには[抽象クラス](./abstract-class.md)があります。`instanceof`演算子は抽象クラスについても使うことができます。 57 | 58 | ```ts twoslash 59 | abstract class AbstractClass {} 60 | class ConcreteClass extends AbstractClass {} 61 | const obj = new ConcreteClass(); 62 | console.log(obj instanceof AbstractClass); 63 | // @log: true 64 | ``` 65 | -------------------------------------------------------------------------------- /docs/reference/object-oriented/class/methods.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: メソッド 3 | --- 4 | 5 | # メソッド (method) 6 | 7 | JavaScriptのクラスにメソッドを実装するには、メソッド構文を用います。 8 | 9 | ```js twoslash 10 | class Greeter { 11 | greet(name) { 12 | return `Hello, ${name}!`; 13 | } 14 | } 15 | ``` 16 | 17 | ## メソッドの型注釈 18 | 19 | TypeScriptでは、メソッドの引数と戻り値に型注釈できます。 20 | 21 | ```ts twoslash 22 | class Greeter { 23 | greet(name: string): string { 24 | return `Hello, ${name}!`; 25 | } 26 | } 27 | ``` 28 | 29 | メソッドの型注釈は関数宣言構文の型注釈と同じです。引数や戻り値の型注釈を省略することもできます。その場合の振る舞いについては関数宣言を参照してください。 30 | 31 | [関数宣言 (function declaration)](../../functions/function-declaration.md) 32 | -------------------------------------------------------------------------------- /docs/reference/object-oriented/class/readonly-modifier-in-classes.md: -------------------------------------------------------------------------------- 1 | # クラスのreadonly修飾子 2 | 3 | TypeScriptでは、フィールドにreadonly修飾子をつけると、そのフィールドを読み取り専用にできます。 4 | 5 | 読み取り専用フィールドは、コンストラクタかフィールド初期化子でのみ値を代入できます。 6 | 7 | ```ts twoslash 8 | class Octopus { 9 | readonly name: string; 10 | readonly legs = 8; // フィールド初期化子での代入はOK 11 | 12 | constructor() { 13 | this.name = "たこちゃん"; // コンストラクターでの代入はOK 14 | } 15 | } 16 | ``` 17 | 18 | 読み取り専用フィールドは、再代入しようとするとコンパイルエラーになります。 19 | 20 | ```ts twoslash 21 | class Octopus { 22 | readonly name: string; 23 | readonly legs = 8; // フィールド初期化子での代入はOK 24 | 25 | constructor() { 26 | this.name = "たこちゃん"; // コンストラクターでの代入はOK 27 | } 28 | } 29 | // ---cut--- 30 | // @errors: 2540 31 | const octopus = new Octopus(); 32 | octopus.legs = 16; 33 | ``` 34 | 35 | メソッド内の処理であっても、読み取り専用フィールドへの再代入は許されません。 36 | 37 | ```ts twoslash 38 | // @errors: 2540 39 | class Octopus { 40 | readonly name = "たこちゃん"; 41 | 42 | setName(newName: string): void { 43 | this.name = newName; 44 | } 45 | } 46 | ``` 47 | 48 | ## 関連情報 49 | 50 | [オブジェクト型のreadonlyプロパティ (readonly property)](../../values-types-variables/object/readonly-property.md) 51 | 52 | [インターフェースのreadonly修飾子](../interface/readonly-modifier-in-interfaces.md) 53 | -------------------------------------------------------------------------------- /docs/reference/object-oriented/class/static-fields.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 静的フィールド 3 | --- 4 | 5 | # 静的フィールド (static field) 6 | 7 | JavaやPHPには静的フィールド(static field)という概念があります。通常のフィールドはインスタンスのプロパティですが、静的フィールドはクラスのプロパティです。JavaやPHPではstaticキーワードで静的フィールドを宣言できます。 8 | 9 | ```java title="Java" 10 | class SomeClass { 11 | public static Integer field = 123; 12 | } 13 | 14 | class Main { 15 | public static void main(String[] args) { 16 | System.out.println(SomeClass.field); //=> 123 17 | } 18 | } 19 | ``` 20 | 21 | ```php title="PHP" 22 | class SomeClass 23 | { 24 | public static $field = 123; 25 | } 26 | 27 | var_dump(SomeClass::$field); //=> int(123) 28 | ``` 29 | 30 | JavaScriptやTypeScriptでもstaticキーワードを使った静的フィールドの宣言ができます。 31 | 32 | ```ts title="TypeScript" twoslash 33 | class SomeClass { 34 | static field: number = 123; 35 | } 36 | console.log(SomeClass.field); 37 | // @log: 123 38 | ``` 39 | 40 | ## 静的フィールドの型推論 41 | 42 | TypeScriptの静的フィールドは初期値がセットされている場合、その初期値からフィールドの型が型推論されます。そのため、フィールドの型注釈が省略できます。 43 | 44 | ```ts twoslash 45 | class SomeClass { 46 | static field = 123; 47 | } 48 | ``` 49 | 50 | ## 静的フィールドとアクセス修飾子 51 | 52 | TypeScriptの静的フィールドはアクセス修飾子を組み合わせられます。 53 | 54 | ```ts twoslash 55 | class SomeClass { 56 | private static field: number; 57 | } 58 | ``` 59 | 60 | [アクセス修飾子 (access modifier)](access-modifiers.md) 61 | 62 | ## 読み取り専用の静的フィールド 63 | 64 | TypeScriptの静的フィールドはreadonly修飾子をつけると読み取り専用になります。 65 | 66 | ```ts twoslash 67 | class SomeClass { 68 | static readonly field: number; 69 | } 70 | ``` 71 | 72 | [クラスのreadonly修飾子](readonly-modifier-in-classes.md) 73 | -------------------------------------------------------------------------------- /docs/reference/object-oriented/class/static-methods.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 静的メソッド 3 | --- 4 | 5 | # 静的メソッド (static method) 6 | 7 | JavaやPHPには静的メソッド(static method)という概念があります。Rubyではクラスメソッドに相当します。通常のメソッドはインスタンスに属しますが、静的メソッドはクラスに属します。JavaやPHPではstaticキーワードで静的フィールドを宣言できます。 8 | 9 | ```java title="Java" 10 | class SomeClass { 11 | static public void doSomething() { 12 | // ... 13 | } 14 | } 15 | 16 | class Main { 17 | public static void main(String[] args) { 18 | SomeClass.doSomething(); 19 | } 20 | } 21 | ``` 22 | 23 | ```php title="PHP" 24 | class SomeClass 25 | { 26 | public static function doSomething() 27 | { 28 | // ... 29 | } 30 | } 31 | 32 | SomeClass::doSomething(); 33 | ``` 34 | 35 | JavaScriptやTypeScriptでもstaticキーワードを使った静的メソッドの宣言ができます。 36 | 37 | ```js title="JavaScript" twoslash 38 | class SomeClass { 39 | static doSomething() { 40 | // ... 41 | } 42 | } 43 | SomeClass.doSomething(); 44 | ``` 45 | 46 | ## 静的メソッドとアクセス修飾子 47 | 48 | TypeScriptの静的メソッドはアクセス修飾子を組み合わせられます。 49 | 50 | ```ts twoslash 51 | class SomeClass { 52 | private static doSomething() { 53 | // ... 54 | } 55 | } 56 | ``` 57 | 58 | [アクセス修飾子 (access modifier)](access-modifiers.md) 59 | -------------------------------------------------------------------------------- /docs/reference/object-oriented/interface/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: "インターフェース" 3 | slug: /reference/object-oriented/interface 4 | --- 5 | 6 | # インターフェース (interface) 7 | 8 | インターフェースはクラスが実装すべきフィールドやメソッドを定義した型です。クラスはインターフェースを実装することで、インターフェースが求めるメソッド名や引数の型に則っているかをチェックすることができます。 9 | 10 | JavaやPHPなどの言語では、インターフェースが定義できますが、JavaScriptにはそれに相当する構文がありません。一方、TypeScriptにはインターフェースがあります。 11 | 12 | TypeScriptで定義されたインターフェースは、コンパイルチェックに活用された後、JavaScriptコードを生成する過程で消されるため、インターフェースがJavaScript実行時に影響することはありません。 13 | 14 | ## インターフェースを定義する 15 | 16 | TypeScriptでは`interface`キーワードでインターフェースを定義できます。 17 | 18 | ```ts twoslash 19 | interface SomeInterface { 20 | method1(): void; 21 | method2(arg: string): void; 22 | } 23 | ``` 24 | 25 | TypeScriptではメソッドだけでなく、パブリックフィールドも定義できます。 26 | 27 | ```ts twoslash 28 | interface SomeInterface { 29 | field: string; 30 | } 31 | ``` 32 | 33 | ## インターフェースと構造的部分型 34 | 35 | Javaなどのオブジェクト指向言語ではクラスの抽象的な型定義として利用されます。そのため、インターフェース単体では利用されず、特定のクラスがインターフェースを継承し実装を追加することで初めて効果を発揮します。 36 | 37 | TypeScriptでもインターフェースをクラスに実装させることはできますが、それに加えて、TypeScriptは構造的部分型なので、インターフェースと実装関係がないオブジェクトの型注釈としても利用できます。 38 | 39 | ```ts twoslash 40 | interface Person { 41 | name: string; 42 | age: number; 43 | } 44 | 45 | const taro: Person = { 46 | name: "太郎", 47 | age: 12, 48 | }; 49 | ``` 50 | 51 | [構造的部分型 (structural subtyping)](../../values-types-variables/structural-subtyping.md) 52 | -------------------------------------------------------------------------------- /docs/reference/object-oriented/interface/implementing-interfaces.md: -------------------------------------------------------------------------------- 1 | # インターフェースを実装する 2 | 3 | TypeScriptでは、クラスがインターフェースを実装できます。実装するには`implements`キーワードを用います。 4 | 5 | ```ts twoslash 6 | interface Human { 7 | think(): void; 8 | } 9 | 10 | class Developer implements Human { 11 | think(): void { 12 | console.log("どういう実装にしようかな〜"); 13 | } 14 | } 15 | ``` 16 | 17 | インターフェースを複数指定することもできます。そのときは`,`でインターフェースを区切り列挙します。 18 | 19 | ```ts twoslash 20 | interface Human { 21 | think(): void; 22 | } 23 | 24 | interface Programmer { 25 | writeCode(): void; 26 | } 27 | 28 | class TypeScriptProgrammer implements Human, Programmer { 29 | think(): void { 30 | console.log("どういうコードにしようかな〜"); 31 | } 32 | 33 | writeCode(): void { 34 | console.log("カタカタ"); 35 | } 36 | } 37 | ``` 38 | 39 | インターフェースで定義されたフィールドをクラスで実装するには、クラス側にはフィールドを定義します。 40 | 41 | ```ts twoslash 42 | interface Human { 43 | name: string; 44 | } 45 | 46 | class Developer implements Human { 47 | name: string = "Bob"; 48 | } 49 | ``` 50 | -------------------------------------------------------------------------------- /docs/reference/object-oriented/interface/interface-inheritance.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: インターフェースの継承 3 | --- 4 | 5 | # インターフェースの継承 (inheritance) 6 | 7 | TypeScriptでは、`extends`キーワードを利用して定義済みのインターフェースを継承して、新たにインターフェースを定義することができます。インターフェースを継承した場合、継承元のプロパティの型情報はすべて引き継がれます。新しくプロパティを追加することもできますし、すでに宣言されているプロパティの型を部分型に指定しなおすこともできます。 8 | 9 | ## プロパティを追加する 10 | 11 | ```ts twoslash 12 | interface Person { 13 | name: string; 14 | age: number; 15 | } 16 | 17 | interface Student extends Person { 18 | grade: number; // 学年 19 | } 20 | 21 | interface Teacher extends Person { 22 | students: Student[]; // 生徒 23 | } 24 | 25 | const studentA: Student = { 26 | name: "花子", 27 | age: 10, 28 | grade: 3, 29 | }; 30 | 31 | const teacher: Teacher = { 32 | name: "太郎", 33 | age: 30, 34 | students: [studentA], 35 | }; 36 | ``` 37 | 38 | ## プロパティを部分型に宣言しなおす 39 | 40 | ある型からその型のリテラル型にすることも、ユニオン型から部分的に選択することもTypeScriptではそれぞれサブタイプにしていることと同じ意味があります。もちろん他のオブジェクト指向の言語と同じようにサブクラスにすることもできます。 41 | 42 | ### リテラル型に変更する 43 | 44 | ```ts twoslash 45 | interface WebPage { 46 | path: string; 47 | } 48 | 49 | interface IndexPage extends WebPage { 50 | path: "/"; 51 | } 52 | ``` 53 | 54 | ### ユニオン型から選ぶ 55 | 56 | ```ts twoslash 57 | interface Person { 58 | age: number | undefined; 59 | } 60 | 61 | interface Student extends Person { 62 | age: number; 63 | } 64 | ``` 65 | -------------------------------------------------------------------------------- /docs/reference/object-oriented/interface/readonly-modifier-in-interfaces.md: -------------------------------------------------------------------------------- 1 | # インターフェースのreadonly修飾子 2 | 3 | TypeScriptのインターフェースでは、フィールドにreadonly修飾子をつけることで読み取り専用のフィールドが定義できます。 4 | 5 | ```ts twoslash 6 | interface SomeInterface { 7 | readonly field: number; 8 | } 9 | ``` 10 | 11 | ## 関連情報 12 | 13 | [クラスのreadonly修飾子](../class/readonly-modifier-in-classes.md) 14 | 15 | [オブジェクト型のreadonlyプロパティ (readonly property)](../../values-types-variables/object/readonly-property.md) 16 | -------------------------------------------------------------------------------- /docs/reference/object-oriented/javascript-vs-typescript-in-oop-features.md: -------------------------------------------------------------------------------- 1 | # JavaScriptとTypeScriptのオブジェクト指向機能の比較 2 | 3 | 簡易な一覧ですが、型に関する機能が拡張されていることがわかると思います。 4 | 5 | | 機能名 | JavaScript | TypeScript | 6 | | :------------------------- | :--------- | :--------- | 7 | | クラス構文 | ○ | ○ | 8 | | クラス継承 | ○ | ○ | 9 | | super | ○ | ○ | 10 | | コンストラクタ | ○ | ○ | 11 | | 抽象クラス(abstract) | ✕ | ○ | 12 | | 抽象メソッド | ✕ | ○ | 13 | | アクセス修飾子 | △ | ○ | 14 | | インターフェース | ✕ | ○ | 15 | | ジェネリクス | ✕ | ○ | 16 | | 静的プロパティ | △ | ○ | 17 | | 静的メソッド | △ | ○ | 18 | | finalクラス / sealedクラス | ✕ | ✕ | 19 | | finalメソッド | ✕ | ✕ | 20 | 21 | クラスにかかわらずTypeScriptの特徴となるのはコーディング中に型が不適切な場合はコンパイルエラーを教えてくれることです。JavaScriptの場合は基本的に実行を行い不正な型が発生した場合に型エラーを知ることになります。TypeScriptコードに問題がなく型安全と判断された場合に限りコンパイルを行うことができます。また出力されたJavaScriptファイルには型情報は除かれます。 22 | -------------------------------------------------------------------------------- /docs/reference/statements/for-of.md: -------------------------------------------------------------------------------- 1 | # for-of文 - 拡張for文 2 | 3 | JavaScriptで配列をループするのに使えるのがfor-of構文です。PHPの`foreach`やPythonの`for in`と使い勝手が似ている構文です。 4 | 5 | ```js 6 | for (変数 of 配列) { 7 | 文; 8 | } 9 | ``` 10 | 11 | このとき変数側に対して型を書くことができないことに注意してください。 12 | 13 | 次の例は、配列`[1, 2, 3]`をループして順番に`1`、`2`、`3`を出力するものです。 14 | 15 | ```js twoslash 16 | const numbers = [1, 2, 3]; 17 | for (const n of numbers) { 18 | console.log(n); 19 | } 20 | ``` 21 | 22 | ## for-ofでインデックスを取得する 23 | 24 | JavaScriptで、for-ofで配列のインデックスと値を一緒に得るには、`entries`メソッドを組み合わせます。 25 | 26 | ```js twoslash 27 | const words = ["I", "love", "TypeScript"]; 28 | for (const [index, word] of words.entries()) { 29 | console.log(index, word); 30 | } 31 | // @log: 0 I 32 | 33 | // @log: 1 love 34 | 35 | // @log: 2 TypeScript 36 | ``` 37 | 38 | ## 関連情報 39 | 40 | [配列をループする方法](../values-types-variables/array/how-to-loop-an-array.md) 41 | 42 | [オブジェクトをループする方法](../values-types-variables/object/how-to-loop-an-object.md) 43 | -------------------------------------------------------------------------------- /docs/reference/statements/if-else.md: -------------------------------------------------------------------------------- 1 | # if-else文 2 | 3 | JavaScriptの条件分岐はJavaやPHPと同じようにif-else構文を用います。 4 | 5 | ```js twoslash 6 | if (value === 0) { 7 | // ... 8 | } else { 9 | // ... 10 | } 11 | ``` 12 | 13 | JavaScriptにもelse-ifがあります。`else if`のようにelseとifの間にはスペースが必要です。 14 | 15 | ```js twoslash 16 | if (value === 0) { 17 | // ... 18 | } else if (value === 1) { 19 | // ... 20 | } else { 21 | // ... 22 | } 23 | ``` 24 | 25 | JavaScriptのif-elseは文です。式ではないので、条件分岐を直接変数に代入することはできません。 26 | 27 | ```js 28 | // こんな書き方はできない 29 | const result = if (value === 0) "OK" else "NG"; 30 | ``` 31 | 32 | 式で条件分岐を使いたい場合は三項演算子(ternary operator)を用います。 33 | 34 | ```js twoslash 35 | const result = value === 0 ? "OK" : "NG"; 36 | ``` 37 | 38 | [三項演算子 (ternary operator)](ternary-operator.md) 39 | 40 | 上のコードと同じロジックをif-elseで書く場合は、`if`ブロックの手前で結果を代入する変数を`let`で宣言します。 41 | 42 | ```js twoslash 43 | let result; 44 | if (value === 0) { 45 | result = "OK"; 46 | } else { 47 | result = "NG"; 48 | } 49 | ``` 50 | 51 | ## 関連情報 52 | 53 | [switch文](switch.md) 54 | -------------------------------------------------------------------------------- /docs/reference/statements/switch-and-variable-scope.md: -------------------------------------------------------------------------------- 1 | # switchと変数スコープ 2 | 3 | JavaScriptでは、`switch`ごとに変数スコープが作られます。 4 | 5 | ```ts twoslash 6 | switch ( 7 | true // 変数スコープその1 8 | ) { 9 | default: 10 | switch ( 11 | true // 変数スコープその2 12 | ) { 13 | default: 14 | // ... 15 | } 16 | } 17 | ``` 18 | 19 | ## caseの変数スコープはない 20 | 21 | `case`ごとには変数スコープが作られません。複数の`case`がある場合、`switch`全体で変数スコープを共有します。そのため、複数の`case`で同じ変数名を宣言すると実行時エラーが発生します。 22 | 23 | 24 | ```ts twoslash 25 | let x = 1; 26 | switch (x) { 27 | case 1: 28 | const sameName = "A"; 29 | break; 30 | case 2: 31 | const sameName = "B"; 32 | // @error: SyntaxError: Identifier 'sameName' has already been declared 33 | break; 34 | } 35 | // @noErrors 36 | ``` 37 | 38 | TypeScriptでは、同じ変数名を宣言するとコンパイルエラーを出します。 39 | 40 | ```ts twoslash 41 | // @errors: 2451 42 | let x = 1; 43 | switch (x) { 44 | case 1: 45 | const sameName = "A"; 46 | break; 47 | case 2: 48 | const sameName = "B"; 49 | break; 50 | } 51 | ``` 52 | 53 | ## caseに変数スコープを作る方法 54 | 55 | caseに変数スコープを作るには、中カッコでcase節を囲みます。 56 | 57 | ```ts twoslash 58 | let x = 1; 59 | switch (x) { 60 | case 1: { 61 | const sameName = "A"; 62 | break; 63 | } 64 | case 2: { 65 | const sameName = "B"; 66 | break; 67 | } 68 | } 69 | ``` 70 | 71 | こうすると、JavaScriptの実行時エラーも、TypeScriptのコンパイルエラーも発生しなくなります。 72 | 73 | 74 | 75 | 🌏JavaScriptのswitchは全体で1つの変数スコープ 76 | 😕caseレベルのスコープはない 77 | 78 | もしも複数のcaseで同じ変数名を宣言すると… 79 | 🔥JavaScript → 実行時エラー 80 | ⛔️TypeScript → コンパイルエラー 81 | 82 | ✅caseに{}を書くと固有のスコープが作れる 83 | 84 | 85 | -------------------------------------------------------------------------------- /docs/reference/statements/switch-fallthrough.md: -------------------------------------------------------------------------------- 1 | # switchのフォールスルー問題 2 | 3 | JavaScriptのswitchの`case`には、分岐を抜けさせる働きがありません。分岐を抜けるには、`break`が必要です。`break`を書かない場合、次の分岐も実行されます。この仕様をフォールスルー(fallthrough)と言います。 4 | 5 | ```ts twoslash 6 | let s = "A"; 7 | switch (s) { 8 | case "A": // breakが無い分岐 9 | console.log(1); 10 | case "B": // この分岐にも処理が続く 11 | console.log(2); 12 | } 13 | // @log: 1 2 の順で出力される 14 | ``` 15 | 16 | フォールスルーはしばしばバグの原因になります。TypeScriptでは、コンパイラオプション`noFallthroughCasesInSwitch`を`true`にすると、フォールスルーを警告するようになります。このオプションは有効化しておきましょう。 17 | 18 | ```ts twoslash 19 | // @noFallthroughCasesInSwitch: true 20 | // @errors: 7029 21 | let s = "A"; 22 | switch (s) { 23 | case "A": 24 | console.log(1); 25 | case "B": 26 | console.log(2); 27 | } 28 | ``` 29 | 30 | [noFallthroughCasesInSwitch](../tsconfig/nofallthroughcasesinswitch.md) 31 | 32 | 33 | 34 | 😴JavaScriptのswitchのcaseには、分岐を抜けさせる働きがない 35 | ⏩breakを書かないと次の分岐も実行される(フォールスルー) 36 | 🐞フォールスルーはバグになりがち 37 | ✅TypeScriptではnoFallthroughCasesInSwitchを有効にするとフォールスルーが検出される 38 | 39 | 40 | -------------------------------------------------------------------------------- /docs/reference/statements/ternary-operator.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 三項演算子 3 | --- 4 | 5 | # 三項演算子 (ternary operator) 6 | 7 | JavaScriptの三項演算子(ternary operator)は、条件分岐ができる演算子です。条件式、真の場合の値、偽の場合の値の三項を取るため三項演算子と呼ばれています。 8 | 9 | ```js 10 | 条件式 ? 真の場合の値 : 偽の場合の値; 11 | ``` 12 | 13 | 演算の結果は変数に代入できます。 14 | 15 | ```js twoslash 16 | const age = 20; 17 | const drink = age >= 20 ? "ビール" : "ジュース"; 18 | console.log(drink); 19 | // @log: "ビール" 20 | ``` 21 | 22 | 条件分岐といえばif-elseですが、if-elseは構文なので上のようにif-elseを直接、値を返すような書き方はできません。 23 | 24 | ```js 25 | // こうした書き方はできない 26 | const drink = if (age >= 20) "ビール" else "ジュース"; 27 | ``` 28 | 29 | 三項演算子は条件をネストできます。 30 | 31 | ```js twoslash 32 | const extension = "ts"; 33 | const language = 34 | extension === "js" 35 | ? "JavaScript" 36 | : extension === "ts" 37 | ? "TypeScript" 38 | : extension === "java" 39 | ? "Java" 40 | : "不明"; 41 | ``` 42 | 43 | 上のコードと同等の処理をif-elseで書くと次のようになります。 44 | 45 | ```js twoslash 46 | const extension = "ts"; 47 | let language; 48 | if (extension === "js") { 49 | language = "JavaScript"; 50 | } else if (extension === "ts") { 51 | language = "TypeScript"; 52 | } else if (extension === "java") { 53 | language = "Java"; 54 | } else { 55 | language = "不明"; 56 | } 57 | ``` 58 | 59 | ## 関連情報 60 | 61 | [if-else文](if-else.md) 62 | 63 | [switch文](switch.md) 64 | -------------------------------------------------------------------------------- /docs/reference/tsconfig/alwaysstrict.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: JavaScriptのstrictモードを有効にする 3 | tags: [strict] 4 | --- 5 | 6 | # alwaysStrict 7 | 8 | `alwaysStrict`はJavaScriptのstrictモードを有効にするコンパイラオプションです。 9 | 10 | - デフォルト: [strict](./strict.md)が有効の場合は`true`、それ以外は`false` 11 | - 追加されたバージョン: 2.1 12 | - TypeScript公式が有効化推奨 13 | 14 | ## 解説 15 | 16 | `'use strict'`を各ファイルの先頭に付加します。 17 | -------------------------------------------------------------------------------- /docs/reference/tsconfig/exactoptionalpropertytypes.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: オプションプロパティにundefinedの代入することを禁止する 3 | --- 4 | 5 | # exactOptionalPropertyTypes 6 | 7 | `exactOptionalPropertyTypes`はオプションプロパティに`undefined`の代入することを禁止するコンパイラオプションです。 8 | 9 | - デフォルト: `false` 10 | - 追加されたバージョン: 4.4 11 | - TypeScript公式が有効化推奨 12 | 13 | ## 解説 14 | 15 | 今までオプション修飾子は値を設定しないことに加えて`undefined`を意図的に設定することができました。 16 | 17 | ```ts twoslash 18 | interface User { 19 | name: string; 20 | nationality?: "India" | "China"; 21 | } 22 | 23 | const user1: User = { 24 | name: "Srinivasa Aiyangar Ramanujan", 25 | nationality: "India", 26 | }; 27 | 28 | const user2: User = { 29 | name: "Sergei Vasilevich Rachmaninov", 30 | nationality: undefined, 31 | }; 32 | 33 | const user3: User = { 34 | name: "Yekaterina II Alekseyevna", 35 | }; 36 | ``` 37 | 38 | 値が未定義であることと値が`undefined`であることは厳密には動作が異なります。たとえば`Object.keys()`は最たる例で、上記の`user1, user2, user3`にそれぞれ`Object.keys()`を適用すれば結果は次のようになります。 39 | 40 | ```ts twoslash 41 | // user1 42 | ["name", "nationality"]; 43 | // user2 44 | ["name", "nationality"]; 45 | // user3 46 | ["name"]; 47 | ``` 48 | 49 | この差異が意図しない実行時エラーを生むことがあります。意図する値が設定されていれば(この場合`'India' | 'China'`)`nationality`は`Object.keys()`に含まれるべきですが`undefined`のときは結局その先で値の存在チェックが必要になります。 50 | 51 | このオプションを有効にすると`interface, type`でオプション修飾子を持つキーはその値がキー自体を持たないようにしなければなりません。先ほどの例では`undefined`を代入した`user2`で次のようなエラーが発生します。 52 | 53 | ```ts twoslash 54 | // @exactOptionalPropertyTypes: true 55 | // @errors: 2375 56 | interface User { 57 | name: string; 58 | nationality?: "India" | "China"; 59 | } 60 | 61 | const user1: User = { 62 | name: "Srinivasa Aiyangar Ramanujan", 63 | nationality: "India", 64 | }; 65 | 66 | const user2: User = { 67 | name: "Sergei Vasilevich Rachmaninov", 68 | nationality: undefined, 69 | }; 70 | 71 | const user3: User = { 72 | name: "Yekaterina II Alekseyevna", 73 | }; 74 | ``` 75 | 76 | どうしてもキーに`undefined`も指定したい場合はオプション修飾子に加えて`undefined`のユニオン型を付加してください。 77 | -------------------------------------------------------------------------------- /docs/reference/tsconfig/noimplicitany.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: 暗黙のany型を禁ずる 3 | tags: [strict] 4 | --- 5 | 6 | # noImplicitAny 7 | 8 | `noImplicitAny`は暗黙のany型を禁止するコンパイラオプションです。 9 | 10 | - デフォルト: [strict](./strict.md)が有効の場合は`true`、それ以外は`false` 11 | - 追加されたバージョン: - 12 | - TypeScript公式が有効化推奨 13 | 14 | ## 暗黙のanyの問題点 15 | 16 | 型注釈もなく型推論もできない場合、TypeScriptは変数の型を`any`にします。これを暗黙のanyといいます。特に引数やプロパティで暗黙のanyになることが多いです。 17 | 18 | ```ts twoslash title="暗黙のanyが発生する例" 19 | // @noImplicitAny: false 20 | function foo(param) {} 21 | // ^? 22 | 23 | class Bar { 24 | private prop; 25 | // ^? 26 | } 27 | ``` 28 | 29 | any型の変数には型チェックが無いため、バグの危険性が増します。 30 | 31 | ```ts twoslash 32 | function increment(number) { 33 | console.log(number + 1); 34 | } 35 | increment("1"); 36 | // @log: "11" 37 | increment(undefined); 38 | // @log: NaN 39 | // @noImplicitAny: false 40 | ``` 41 | 42 | ## `noImplicitAny`で暗黙のanyを防ぐ 43 | 44 | `noImplicitAny`を`true`にすると、変数が暗黙のanyになることを避けられます。TypeScriptは暗黙のanyになる変数を見つけると、警告を出すようになります。 45 | 46 | ```ts twoslash title="暗黙のanyが警告される例" 47 | // @noImplicitAny: true 48 | // @errors: 7006 7008 49 | function foo(param) {} 50 | 51 | class Bar { 52 | private prop; 53 | } 54 | ``` 55 | 56 | ## 関数の戻り値の型 57 | 58 | 関数の戻り値の型は型注釈がなくても、TypeScriptが型推論可能なため暗黙のanyにはなりません。したがって、型注釈の無い戻り値は、`noImplicitAny`を有効にしても警告は出ません。 59 | 60 | ```ts twoslash 61 | function foo() { 62 | // ^? 63 | return 1; 64 | } 65 | ``` 66 | 67 | 戻り値の型注釈を必須にしたい場合は、[`noImplicitReturns`](./noimplicitreturns.md)を有効にしてください。 68 | 69 | 70 | 71 | 😢TypeScriptは型注釈がないOR型推論不能の場合、型をanyにする(暗黙のany) 72 | 🙅‍♂️noImplicitAnyは暗黙のanyを禁止するコンパイラオプション 73 | 😊これをtrueにすると暗黙のanyが警告される 74 | ✅有効化推奨のオプション 75 | 76 | 77 | 78 | ## 関連情報 79 | 80 | [strict](./strict.md) 81 | 82 | [any型](../values-types-variables/any.md) 83 | 84 | [関数宣言](../functions/function-declaration.md) 85 | 86 | [フィールド](../object-oriented/class/fields.md) 87 | -------------------------------------------------------------------------------- /docs/reference/tsconfig/noimplicitreturns.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: 関数戻り値の型注釈を必須にする 3 | --- 4 | 5 | # noImplicitReturns 6 | 7 | `noImplicitReturns`は関数戻り値の型注釈を必須にするコンパイラオプションです。 8 | 9 | - デフォルト: `false` 10 | - 追加されたバージョン: 1.8 11 | 12 | ## 解説 13 | 14 | 戻り値が`void`型以外の関数ですべての条件分岐において値を返しているかを厳密に評価します。 15 | 16 | ```ts twoslash 17 | // @noErrors 18 | function negaposi(num: number): string { 19 | if (num > 0) { 20 | return "positive"; 21 | } else if (num < 0) { 22 | return "negative"; 23 | } 24 | } 25 | ``` 26 | 27 | このオプションを有効にすると次のようなエラーが発生します。 28 | 29 | ```ts twoslash 30 | // @noImplicitReturns: true 31 | // @errors: 2366 32 | function negaposi(num: number): string { 33 | if (num > 0) { 34 | return "positive"; 35 | } else if (num < 0) { 36 | return "negative"; 37 | } 38 | } 39 | ``` 40 | 41 | これを回避するためには条件分岐の場合分けのときに値を返し忘れないように設計します。 42 | 43 | ```ts twoslash 44 | function negaposi(num: number): string { 45 | if (num > 0) { 46 | return "positive"; 47 | } else if (num < 0) { 48 | return "negative"; 49 | } 50 | 51 | return "this is 0"; 52 | } 53 | ``` 54 | -------------------------------------------------------------------------------- /docs/reference/tsconfig/nopropertyaccessfromindexsignature.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: インデックス型のプロパティ参照に[]を必須にする 3 | --- 4 | 5 | # noPropertyAccessFromIndexSignature 6 | 7 | `noPropertyAccessFromIndexSignature`はインデックス型のプロパティ参照に`[]`を必須にするコンパイラオプションです。 8 | 9 | - デフォルト: `false` 10 | - 追加されたバージョン: 4.2 11 | 12 | ## 解説 13 | 14 | `noUncheckedIndexedAccess`と同様にインデックス型を持つオブジェクトに対する型評価です。インデックス型に対するアクセスをインデックス記法に強制します。 15 | 16 | ドット記法とインデックス記法についてですが、次のようにあるオブジェクトがあるとしてドット(`.`)でプロパティアクセスをしているものがドット記法、ブラケット(`[]`)でアクセスをしているものがインデックス記法です。 17 | 18 | ```ts twoslash 19 | type SystemTerms = { 20 | en: string; 21 | [key: string]: string; 22 | }; 23 | 24 | const butterfly: SystemTerms = { 25 | en: "Butterfly", 26 | fr: "Papillon", 27 | it: "Farfalla", 28 | es: "Mariposa", 29 | }; 30 | 31 | // dot syntax 32 | butterfly.en; 33 | // indexed syntax 34 | butterfly["en"]; 35 | ``` 36 | 37 | `SystemTerms`は`noUncheckedIndexedAccess`にて登場した型と同じものでシステムにおける単語、用語のうち英語は担保し他言語の存在は曖昧なものにしています。 38 | 39 | ```ts twoslash 40 | type SystemTerms = { 41 | en: string; 42 | [key: string]: string; 43 | }; 44 | 45 | const butterfly: SystemTerms = { 46 | en: "Butterfly", 47 | fr: "Papillon", 48 | it: "Farfalla", 49 | es: "Mariposa", 50 | }; 51 | // ---cut--- 52 | console.log(butterfly.fr); 53 | // @log: "Papillon" 54 | ``` 55 | 56 | 存在が不確かなプロパティへのアクセスについて、ドット記法でアクセスするときに、このオプションを有効にすると次のようなエラーが発生します。 57 | 58 | ```ts twoslash 59 | // @noPropertyAccessFromIndexSignature: true 60 | type SystemTerms = { 61 | en: string; 62 | [key: string]: string; 63 | }; 64 | 65 | const butterfly: SystemTerms = { 66 | en: "Butterfly", 67 | fr: "Papillon", 68 | it: "Farfalla", 69 | es: "Mariposa", 70 | }; 71 | // ---cut--- 72 | // @errors: 4111 73 | console.log(butterfly.fr); 74 | ``` 75 | 76 | このようにインデックス型へのドット記法でのアクセスが禁止されます。 77 | -------------------------------------------------------------------------------- /docs/reference/tsconfig/nounusedlocals.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: 使われていない変数を禁止する 3 | --- 4 | 5 | # noUnusedLocals 6 | 7 | `noUnusedLocals`は使われていない変数を禁止するコンパイラオプションです。 8 | 9 | - デフォルト: `false` 10 | - 追加されたバージョン: 2.0 11 | 12 | ## 解説 13 | 14 | 宣言したにもかかわらず使用されていない変数を禁止します。 15 | 16 | ```ts twoslash 17 | function add(n1: number, n2: number): number { 18 | const message: string = `the sum is ${n1 + n2}`; 19 | 20 | return n1 + n2; 21 | } 22 | ``` 23 | 24 | このオプションを有効にすると次のようなエラーが発生します。 25 | 26 | ```ts twoslash 27 | // @noUnusedLocals: true 28 | // @errors: 6133 29 | function add(n1: number, n2: number): number { 30 | const message: string = `the sum is ${n1 + n2}`; 31 | 32 | return n1 + n2; 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/reference/tsconfig/nounusedparameters.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: 使われていない引数を禁止する 3 | --- 4 | 5 | # noUnusedParameters 6 | 7 | `noUnusedParameters`は使われていない引数を禁止するコンパイラオプションです。 8 | 9 | - デフォルト: `false` 10 | - 追加されたバージョン: 2.0 11 | 12 | ## 解説 13 | 14 | 関数で使用していない引数を禁止します。 15 | 16 | ```ts twoslash 17 | // @noUnusedParameters: false 18 | function add(n1: number, n2: number, n3: number): number { 19 | return n1 + n2; 20 | } 21 | ``` 22 | 23 | このオプションを有効にすると次のようなエラーが発生します。 24 | 25 | ```ts twoslash 26 | // @noUnusedParameters: true 27 | // @errors: 6133 28 | 29 | function add(n1: number, n2: number, n3: number): number { 30 | return n1 + n2; 31 | } 32 | ``` 33 | 34 | これを回避するためには、使用していない引数を`_`で始まる名前に変更します。 35 | 36 | ```ts twoslash 37 | function add(n1: number, n2: number, _n3: number): number { 38 | return n1 + n2; 39 | } 40 | ``` 41 | -------------------------------------------------------------------------------- /docs/reference/tsconfig/strict.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: strict系のオプションを一括で有効化する 3 | tags: [strict] 4 | --- 5 | 6 | # strict 7 | 8 | `strict`はstrict系のコンパイラオプションを一括で有効化するコンパイラオプションです。 9 | 10 | - デフォルト: `false` 11 | - 追加されたバージョン: 2.3 12 | - TypeScript公式が有効化推奨 13 | 14 | ## 解説 15 | 16 | このオプションは**TypeScript4.4時点で**次の8個のオプションをすべて有効にしていることと同じです。スクラッチから開発するのであれば有効にしておいて差し支えないでしょう。 17 | 18 | - noImplicitAny 19 | - strictNullChecks 20 | - strictFunctionTypes 21 | - strictBindCallApply 22 | - strictPropertyInitialization 23 | - noImplicitThis 24 | - useUnknownInCatchVariables 25 | - alwaysStrict 26 | 27 | この説明にTypeScriptのバージョンが明記されているのは、今後のバージョンで**オプションが追加または廃止されることがありうる**からです。より安定したオプションを設定したい場合は`strict`ではなく個々のオプションを有効にしてください。このオプションを有効にして個々のオプションを無効にした場合個々の設定が優先されます。 28 | -------------------------------------------------------------------------------- /docs/reference/tsconfig/strictpropertyinitialization.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: クラスプロパティの初期化を必須にする 3 | tags: [strict] 4 | --- 5 | 6 | # strictPropertyInitialization 7 | 8 | `strictPropertyInitialization`はクラスプロパティの初期化を必須にするコンパイラオプションです。 9 | 10 | - デフォルト: [strict](./strict.md)が有効の場合は`true`、それ以外は`false` 11 | - 追加されたバージョン: 2.7 12 | - TypeScript公式が有効化推奨 13 | 14 | :::caution 15 | 16 | このオプションを効かすには[`strictNullChecks`](./strictnullchecks.md)も`true`する必要があります。 17 | 18 | ::: 19 | 20 | ## 解説 21 | 22 | `strictPropertyInitialization`を`true`にすると、値が初期化されていないクラスプロパティについて警告を出します。 23 | 24 | ```ts twoslash 25 | // @errors: 2564 26 | class Foo { 27 | prop: number; 28 | } 29 | ``` 30 | 31 | 初期化は、次のいずれかで行う必要があります。 32 | 33 | 1. コンストラクタで初期化 34 | 1. 初期化子で初期化 35 | 1. undefinedとのユニオン型で型注釈する 36 | 37 | 次は、コンストラクタで初期化する例です。 38 | 39 | ```ts twoslash 40 | class Foo { 41 | prop: number; 42 | 43 | constructor() { 44 | this.prop = 1; 45 | } 46 | } 47 | ``` 48 | 49 | 次は、[初期化子](../object-oriented/class/field-initializers.md)で初期化する例です。 50 | 51 | ```ts twoslash 52 | class Foo { 53 | prop: number = 1; 54 | // ^^^初期化子 55 | } 56 | ``` 57 | 58 | プロパティの型が`undefined`との[ユニオン型](../values-types-variables/union.md)の場合、初期化しなくても警告が出ません。 59 | 60 | ```ts twoslash 61 | class Foo { 62 | prop: number | undefined; 63 | } 64 | ``` 65 | 66 | プロパティがオプションの場合も警告が出ません。 67 | 68 | ```ts twoslash 69 | class Foo { 70 | prop?: number; 71 | } 72 | ``` 73 | 74 | 75 | 76 | TypeScriptのstrictPropertyInitializationはプロパティの初期化を必須にするコンパイラオプション。 77 | 78 | ⚠️strictNullChecksもtrueする必要あり 79 | ✅コンストラクタで初期化OR初期化子が必須になる 80 | 🙆🏻‍♂️undefinedとのユニオン型で型注釈するのはOK 81 | 82 | 83 | 84 | ## 関連情報 85 | 86 | [strict](./strict.md) 87 | 88 | [フィールド (field)](../object-oriented/class/fields.md) 89 | -------------------------------------------------------------------------------- /docs/reference/tsconfig/useunknownincatchvariables.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: 例外捕捉catch(e)のeをunknown型として扱う 3 | tags: [strict] 4 | --- 5 | 6 | # useUnknownInCatchVariables 7 | 8 | `useUnknownInCatchVariables`は例外捕捉`catch(e)`の`e`をunknown型として扱うコンパイラオプションです。 9 | 10 | - デフォルト: [strict](./strict.md)が有効の場合は`true`、それ以外は`false` 11 | - 追加されたバージョン: 4.4 12 | - TypeScript公式が有効化推奨 13 | 14 | ## 解説 15 | 16 | JavaScript はいかなる値も例外として投げることができます。そのため捕捉した値は`any`型でした。 17 | 18 | ```ts twoslash 19 | // @useUnknownInCatchVariables: false 20 | // case 1 21 | try { 22 | throw new Error(); 23 | } catch (err) { 24 | // ^? 25 | } 26 | 27 | // case 2 28 | try { 29 | throw "This is an error!"; 30 | } catch (err) { 31 | // ^? 32 | } 33 | 34 | // case 3 35 | try { 36 | throw undefined; 37 | } catch (err) { 38 | // ^? 39 | } 40 | ``` 41 | 42 | この混沌は TypeScript4.0 でようやく整理されることとなりました。捕捉した値に対して`unknown`型を明記することによって捕捉した値の型はわからないものの型安全を獲得できるようになりました。 43 | 44 | ```ts twoslash 45 | // @useUnknownInCatchVariables: false 46 | // case 1 47 | try { 48 | throw new Error(); 49 | } catch (err) { 50 | // ^? 51 | } 52 | 53 | // case 2 54 | try { 55 | throw "This is an error!"; 56 | } catch (err: unknown) { 57 | // ^? 58 | } 59 | 60 | // case 3 61 | try { 62 | throw undefined; 63 | } catch (err: unknown) { 64 | // ^? 65 | } 66 | ``` 67 | 68 | 今回のオプションはこの機能を常時有効にするものです。例外が捕捉した値は型の明記をすることなくすべてが`unknown`型として解釈されるようになります。 69 | 70 | ```ts twoslash 71 | // case 1 72 | try { 73 | throw new Error(); 74 | } catch (err) { 75 | // ^? 76 | } 77 | 78 | // case 2 79 | try { 80 | throw "This is an error!"; 81 | } catch (err) { 82 | // ^? 83 | } 84 | 85 | // case 3 86 | try { 87 | throw undefined; 88 | } catch (err) { 89 | // ^? 90 | } 91 | ``` 92 | 93 | また、この制限を緩くしたい。つまり`unknown`型ではなく`any`型にしたいのであれば捕捉した値に対し`any`型を明記してください。 94 | -------------------------------------------------------------------------------- /docs/reference/type-reuse/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: /reference/type-reuse 3 | --- 4 | 5 | # 型の再利用 6 | 7 | TypeScriptでは型から別の型を導き出す機能があります。既存の型を再度利用して、新たな型を生み出すことを本書では「型の再利用」と呼ぶことにします。 8 | 9 | ## 型の再利用のメタファー 10 | 11 | 多くのプログラミング言語では、変数を処理して別の変数を導き出せます。たとえば、あるオブジェクトのキーの配列が欲しいとき、キーの配列を別途宣言してもよいです。しかし、オブジェクトからキーを導きだしたほうが変更に強いコードになります。 12 | 13 | ```ts twoslash 14 | const obj = { a: 1, b: 2, c: 3 }; 15 | const keys1 = ["a", "b", "c"]; 16 | const keys2 = Object.keys(obj); // keys1より保守性が高い 17 | ``` 18 | 19 | 上は変数の再利用の例です。TypeScriptには変数の再利用の型バージョンがあります。それが型の再利用です。たとえば、あるオブジェクトの型からキーの型を導き出すことができます。 20 | 21 | ```ts twoslash 22 | type Obj = { a: string; b: string; c: string }; 23 | type Keys = keyof Obj; 24 | //=> "a" | "b" | "c" 25 | ``` 26 | 27 | 型の再利用とは、変数の再利用のメタファーなのです。 28 | -------------------------------------------------------------------------------- /docs/reference/type-reuse/conditional-types/infer.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: infer 3 | --- 4 | 5 | # infer 6 | 7 | inferはConditional Typesの中で使われる型演算子です。`infer`は「推論する」という意味で`extends`の右辺にのみ書くことができます。 8 | 9 | ## ユーティリティ型`ReturnType`の例から`infer`を知る 10 | 11 | ある関数の戻り値の型を取得するユーティリティ型`ReturnType`があります。`ReturnType`は次のように定義されています。 12 | 13 | ```ts twoslash 14 | // @noErrors 15 | type ReturnType any> = T extends ( 16 | ...args: any 17 | ) => infer R 18 | ? R 19 | : any; 20 | ``` 21 | 22 | 試しに使ってみましょう。 23 | 24 | ```ts twoslash 25 | const request = (url: string): Promise => { 26 | return fetch(url).then((res) => res.text()); 27 | }; 28 | 29 | type X = ReturnType; 30 | // ^? 31 | ``` 32 | 33 | `typeof`は変数から型を取得する演算子です。JavaScriptの`typeof`とは異なるので注意してください。 34 | 35 | [typeof型演算子](../typeof-type-operator.md) 36 | 37 | このように関数`request`の型から戻り値の型を取得することができました。 38 | 39 | ### `ReturnType`の解説 40 | 41 | `ReturnType`の構造を知るためにはまず`T extends (...args: any) => any`が何かを知る必要があります。これは一般的な関数の型を示しています。任意の個数で任意の型の引数を受け取り、任意の型の値を返すことを示しています。`T`は任意の関数を示しています。 42 | そして戻り値の部分が`=> infer R ? R : any`となっており、`T`が関数である場合は戻り値の型である`R`、そうでない場合は`any`を返すという意味になっています。 43 | 総合的に`ReturnType`は`T`が関数に割り当て可能である場合は`R`、そうでない場合は`any`を返します。 44 | 45 | `infer`を使うことによってある型`T`が配列である場合はその要素の型、そうでない場合は`never`を返す`Flatten`を作ってみましょう。 46 | 47 | ```ts twoslash 48 | type Flatten = T extends (infer U)[] ? U : never; 49 | ``` 50 | 51 | この`Flatten`を使ってみましょう。 52 | 53 | ```ts twoslash 54 | type Flatten = T extends (infer U)[] ? U : never; 55 | // ---cut--- 56 | type A = Flatten; 57 | // ^? 58 | type B = Flatten; 59 | // ^? 60 | type C = Flatten; 61 | // ^? 62 | type D = Flatten<[string, number]>; 63 | // ^? 64 | ``` 65 | 66 | 2次元配列に`Flatten`を適用すると1次元配列が返ってくることが、タプル型に`Flatten`を適用するとユニオン型が返ってくることがわかります。 67 | -------------------------------------------------------------------------------- /docs/reference/type-reuse/keyof-type-operator.md: -------------------------------------------------------------------------------- 1 | # keyof型演算子 2 | 3 | `keyof`はオブジェクトの型からプロパティ名を型として返す型演算子です。たとえば、`name`プロパティを持つ型に対して、`keyof`を使うと文字列リテラル型の`"name"`が得られます。 4 | 5 | ```ts twoslash 6 | type Person = { 7 | name: string; 8 | }; 9 | type PersonKey = keyof Person; 10 | // ^? 11 | ``` 12 | 13 | 2つ以上のプロパティがあるオブジェクトの型に`keyof`を使った場合は、すべてのプロパティ名がユニオン型で返されます。 14 | 15 | ```ts twoslash 16 | // @noErrors 17 | type Book = { 18 | title: string; 19 | price: number; 20 | rating: number; 21 | }; 22 | type BookKey = keyof Book; 23 | // 上は次と同じ意味になる 24 | type BookKey = "title" | "price" | "rating"; 25 | ``` 26 | 27 | インデックス型に`keyof`を使うと、インデックスキーの型が返ります。 28 | 29 | ```ts twoslash 30 | type MapLike = { [K: string]: any }; 31 | type MapKeys = keyof MapLike; 32 | // ^? 33 | ``` 34 | 35 | キーが`string`のインデックス型は、`string`ではなく`string | number`が返ります。number型のキーアクセスの`obj[0]`は`obj["0"]`と同じになるからです。 36 | 37 | Mapped Typesに`keyof`を使うと、そのキーの型が返ります。 38 | 39 | ```ts twoslash 40 | type MapLike = { [K in "x" | "y" | "z"]: any }; 41 | type MapKeys = keyof MapLike; 42 | // ^? 43 | ``` 44 | 45 | プロパティを持たないオブジェクトの型に`keyof`を使うと`never`型が返ります。 46 | 47 | ```ts twoslash 48 | type What = keyof {}; 49 | // ^? 50 | ``` 51 | 52 | `any`型に`keyof`を使うと`string | number | symbol`型が返ります。 53 | 54 | ```ts twoslash 55 | type AnyKeys = keyof any; 56 | // ^? 57 | ``` 58 | 59 | ## keyofのメリット 60 | 61 | `keyof`のメリットは、保守性が上がる点です。オブジェクトの型とは別にプロパティ名のユニオン型を定義していると、オブジェクトの型のプロパティを変更したときに、そのユニオン型のほうも修正が必要になります。`keyof`を使って、オブジェクトの型からキーを導出するようにしておけば、変更箇所はオブジェクトの型のところだけになります。 62 | 63 | 加えて、プロパティが何十個もあるようなオブジェクトを想像してみてください。そのプロパティ名のユニオン型を定義する必要が出てきたとします。その際に、プロパティ名をすべて転記するとなると、転記漏れや書き間違いもあるでしょう。そういう場合は`keyof`を使うとそもそも書き写す必要がないため、便利な上に安全なコーディングができます。 64 | 65 | ## keyofはMapped Typesと一緒に使われる 66 | 67 | keyofは単体で使うことよりMapped Typesと組み合わせて使われることが多いです。 68 | 69 | [マップ型 (Mapped Types)](mapped-types.md) 70 | -------------------------------------------------------------------------------- /docs/reference/type-reuse/typeof-type-operator.md: -------------------------------------------------------------------------------- 1 | # typeof型演算子 2 | 3 | TypeScriptの`typeof`は変数から型を抽出する型演算子です。次は、変数`point`に`typeof`型演算子を用いて、`Point`型を定義する例です。このPoint型は次のような型になります。 4 | 5 | ```ts twoslash 6 | const point = { x: 135, y: 35 }; 7 | type Point = typeof point; 8 | // ^? 9 | ``` 10 | 11 | ここで説明したのはTypeScriptのtypeof**型**演算子です。JavaScriptのtypeof演算子と同じ名前ですが、まったく別のものなので注意してください。 12 | 13 | [typeof演算子 (typeof operator)](../values-types-variables/typeof-operator.md) 14 | -------------------------------------------------------------------------------- /docs/reference/type-reuse/utility-types/awaited.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: Promiseの解決値の型を取得する 3 | title: "Awaited" 4 | --- 5 | 6 | `Awaited`は、`Promise`の解決値の型`T`を取得するユーティリティ型です。 7 | `Promise`が解決するまでの非同期処理の結果が必要な場合や、`async`/`await`パターンで複数の入れ子になった`Promise`の中から解決済みの値の型を取り出したい場合に非常に便利です。 8 | 9 | ## Awaited<T>の型引数 10 | 11 | ### T 12 | 13 | 型引数`T`には、任意の型を渡します。それが`Promise`である場合は解決された型である`V`を返します。これは`Promise`が何重にネストしていても、最終的な解決値の型を取得できます。 14 | 15 | ## Awaitedの使用例 16 | 17 | ```ts twoslash 18 | // @errors: 2344 19 | type Awaited1 = Awaited; 20 | // ^? 21 | type Awaited2 = Awaited>; 22 | // ^? 23 | type Awaited3 = Awaited>>; 24 | // ^? 25 | ``` 26 | 27 | ## `Promise`がネストしていても解決された値を取得できるのはなぜか 28 | 29 | まずは`Awaited`の実装を見てみましょう。 30 | 31 | ```ts twoslash 32 | // @noErrors 33 | type Awaited = T extends null | undefined 34 | ? T 35 | : T extends object & { then(onfulfilled: infer F, ...args: infer _): any } 36 | ? F extends (value: infer V, ...args: infer _) => any 37 | ? Awaited 38 | : never 39 | : T; 40 | ``` 41 | 42 | 少々複雑ですが、ひとつずつみていきましょう。 43 | 44 | まず`T`が`null`または`undefined`である場合はそのまま`T`を返します。次に、`T`が`object`であり、`then`メソッドを持つ場合は、その`then`メソッドの第1引数の型を取得します。この型が`Promise`の解決値である場合は再帰的に`Awaited`を適用します。これにより、`Promise`が何重にネストしていても、最終的な解決値の型を取得できるようになります。 45 | -------------------------------------------------------------------------------- /docs/reference/type-reuse/utility-types/exclude.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: 任意の型を除外する 3 | title: "Exclude" 4 | --- 5 | 6 | `Exclude`は、ユニオン型`T`から`U`で指定した型を取り除いたユニオン型を返すユーティリティ型です。 7 | 8 | ## Exclude<T, U>の型引数 9 | 10 | ### T 11 | 12 | 型引数`T`には、ユニオン型を渡します。 13 | 14 | ### U 15 | 16 | 型引数`U`には、`T`から取り除きたい型を渡します。 17 | 18 | ## Excludeの使用例 19 | 20 | ```ts twoslash 21 | type Grade = "A" | "B" | "C" | "D" | "E"; 22 | type PassGrade = Exclude; 23 | ``` 24 | 25 | 上のPassGradeは次の型と同じになります。 26 | 27 | ```ts twoslash 28 | type PassGrade = "A" | "B" | "C" | "D"; 29 | ``` 30 | 31 | `Exclude`の第2引数をユニオン型にすると、複数の型を取り除くこともできます。 32 | 33 | ```ts twoslash 34 | type Grade = "A" | "B" | "C" | "D" | "E"; 35 | type PassGrade = Exclude; 36 | // ^? 37 | ``` 38 | 39 | ## Excludeの注意点 40 | 41 | `U`は`T`の部分集合である制限がありません。つまり、`T`に存在しない型を`U`に入れてしまったり、タイポなどに気をつけなければいけません。次の例は、Pull Requestに関する型と解釈してください。 42 | 43 | ```ts twoslash 44 | type PullRequestState = "draft" | "reviewed" | "rejected"; 45 | type MergeableState = Exclude; 46 | // ^? 47 | ``` 48 | 49 | `MergeableState`は`reviewed`を意味しますが、この`Exclude`の使い方には2つの潜在的な問題があります。 50 | 51 | ### `PullRequestState`に新しい状態が追加された時 52 | 53 | `PullRequestState`に`testFailed`という`MergeableState`に含めたくない状態を追加したとします。するとこの修正に伴って`MergeableState`の第2引数も同時に修正しないといけません。これを忘れると`testFailed`は`MergeableState`に含まれてしまいます。 54 | 55 | ```ts twoslash 56 | type PullRequestState = "draft" | "reviewed" | "rejected" | "testFailed"; 57 | type MergeableState = Exclude; 58 | // ^? 59 | ``` 60 | 61 | ### 変更した場合 62 | 63 | `PullRequestState`の`draft`を`open`に変更しました。この場合も、`Exclude`の第2引数の修正を忘れると`MergeableState`に`open`が含まれてしまいます。 64 | 65 | ```ts twoslash 66 | type PullRequestState = "open" | "reviewed" | "rejected"; 67 | type MergeableState = Exclude; 68 | // ^? 69 | ``` 70 | -------------------------------------------------------------------------------- /docs/reference/type-reuse/utility-types/extract.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: 任意の型だけを抽出する 3 | title: "Extract" 4 | --- 5 | 6 | `Extract`は、ユニオン型`T`から`U`で指定した型だけを抽出した型を返すユーティリティ型です。 7 | 8 | ## Extract<T, U>の型引数 9 | 10 | ### T 11 | 12 | 型引数`T`には、抽出されるほうのユニオン型を渡します。 13 | 14 | ### U 15 | 16 | 型引数`U`には、抽出したい型を渡します。 17 | 18 | ## Extractの使用例 19 | 20 | ```ts twoslash 21 | type Grade = "A" | "B" | "C" | "D" | "E"; 22 | type FailGrade = Extract; 23 | // ^? 24 | ``` 25 | 26 | Extractは2つのユニオン型の共通部分を導き出すことにも使えます。 27 | 28 | ```ts twoslash 29 | type CommonTypes = Extract<"a" | "b" | "c", "b" | "c" | "d">; 30 | // ^? 31 | ``` 32 | 33 | ## 関連情報 34 | 35 | [Exclude<T, U>](exclude.md) 36 | -------------------------------------------------------------------------------- /docs/reference/type-reuse/utility-types/no-infer.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: 型推論を防ぐ 3 | title: NoInfer 4 | --- 5 | 6 | `NoInfer`は、`T`の型推論を防ぐためのユーティリティ型です。 7 | 8 | ## NoInfer<T>の型引数 9 | 10 | ### T 11 | 12 | 型引数`T`には推論を防ぎたい型を代入します。 13 | 14 | ## NoInferの使用例 15 | 16 | まずはNoInferを使用しなかった場合の例です。ジェネリクスを使って`getIndexFromArray`という関数を定義します 17 | 18 | ```ts 19 | function getIndexFromArray(elements: T[], item: T): number { 20 | return elements.findIndex((element) => element === item); 21 | } 22 | 23 | type Fruit = "grape" | "apple" | "banana"; 24 | const fruits: Fruit[] = ["grape", "apple", "banana"]; 25 | getIndexFromArray(fruits, "apple"); 26 | getIndexFromArray(fruits, "peach"); 27 | ``` 28 | 29 | このとき`T`は`"grape" | "apple" | "banana" | "peach"`と推論されてしまいます。しかし第二引数には配列に含まれている要素のみを許容したいです。そこで`NoInfer`を利用することにより`T`の型推論を防ぐことができます。 30 | 31 | ```ts twoslash 32 | function getIndexFromArray( 33 | elements: T[], 34 | item: NoInfer 35 | ): number { 36 | return elements.findIndex((element) => element === item); 37 | } 38 | 39 | type Fruit = "grape" | "apple" | "banana"; 40 | const fruits: Fruit[] = ["grape", "apple", "banana"]; 41 | getIndexFromArray(fruits, "apple"); 42 | // @errors: 2345 43 | getIndexFromArray(fruits, "peach"); 44 | ``` 45 | 46 | ## 関連情報 47 | 48 | [Infer](../../values-types-variables/type-inference.md) 49 | -------------------------------------------------------------------------------- /docs/reference/type-reuse/utility-types/nonnullable.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: nullとundefinedを除外する 3 | title: "NonNullable" 4 | --- 5 | 6 | `NonNullable`は、ユニオン型`T`から`null`と`undefined`を取り除いたユニオン型を返すユーティリティ型です。 7 | 8 | 名前は`NonNullable`ですが`undefined`も取り除くことができます。 9 | 10 | ## NonNullable<T>の型引数 11 | 12 | ### T 13 | 14 | 型引数`T`には、`null`と`undefined`を取り除きたいユニオン型を渡します。 15 | 16 | ## NonNullableの使用例 17 | 18 | ```ts twoslash 19 | type String1 = NonNullable; 20 | // ^? 21 | type String2 = NonNullable; 22 | // ^? 23 | type String3 = NonNullable; 24 | // ^? 25 | type String4 = NonNullable; 26 | // ^? 27 | ``` 28 | 29 | `NonNullable`と`NonNullable`は`never`型になります。 30 | 31 | ```ts twoslash 32 | type Never1 = NonNullable; 33 | // ^? 34 | type Never2 = NonNullable; 35 | // ^? 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/reference/type-reuse/utility-types/omit.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: 任意のプロパティを除いたオブジェクト型を作る 3 | title: "Omit" 4 | --- 5 | 6 | `Omit`は、オブジェクトの型`T`から`Keys`で指定したプロパティを除いたobject型を返すユーティリティ型です。 7 | 8 | ## Omit<T, Keys>の型引数 9 | 10 | ### T 11 | 12 | 型引数`T`にはオブジェクトの型を渡します。 13 | 14 | ### Keys 15 | 16 | `Keys`には引数`T`のプロパティキーを指定します。ここで指定したプロパティキーと一致するプロパティを`T`から除去します。 17 | 18 | ## Omitの使用例 19 | 20 | ```ts twoslash 21 | type User = { 22 | surname: string; 23 | middleName?: string; 24 | givenName: string; 25 | age: number; 26 | address?: string; 27 | nationality: string; 28 | createdAt: string; 29 | updatedAt: string; 30 | }; 31 | type Optional = "age" | "address" | "nationality" | "createdAt" | "updatedAt"; 32 | type Person = Omit; 33 | ``` 34 | 35 | 上の`Person`型は次の型と同じになります。 36 | 37 | ```ts twoslash 38 | type Person = { 39 | surname: string; 40 | middleName?: string; 41 | givenName: string; 42 | }; 43 | ``` 44 | 45 | ## Omitの注意点 46 | 47 | `Omit`の`Keys`に`T`には無いプロパティキーを指定しても、TypeScriptコンパイラーは指摘しません。たとえば、`Keys`にタイポがあっても検出できないので注意が必要です。 48 | 49 | ```ts twoslash 50 | type User = { 51 | surname: string; 52 | middleName?: string; 53 | givenName: string; 54 | age: number; 55 | address?: string; 56 | nationality: string; 57 | createdAt: string; 58 | updatedAt: string; 59 | }; 60 | type Optional = "createdat" | "updatedat" | "age" | "address" | "nationality"; 61 | // ^^ typo ^^ typo 62 | type Person = Omit; 63 | // ^? 64 | // このPersonは下の型になる 65 | ``` 66 | 67 | `User`の`createdAt`、`updatedAt`の`At`は大文字から始まりますが、これに気づかずに小文字で書いてしまったため、`Omit`の結果は`createdAt`と`updatedAt`を含んでしまいます。 68 | 69 | ## 関連情報 70 | 71 | [Pick<T, Keys>](pick.md) 72 | -------------------------------------------------------------------------------- /docs/reference/type-reuse/utility-types/readonly.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: 全プロパティを読み取り専用にする 3 | title: Readonly 4 | --- 5 | 6 | `Readonly`は、オブジェクトの型`T`のプロパティをすべて読み取り専用にするユーティリティ型です。 7 | 8 | ## Readonly<T>の型引数 9 | 10 | ### T 11 | 12 | 型引数`T`にはオブジェクトの型を代入します。 13 | 14 | ## Readonlyの使用例 15 | 16 | ```ts twoslash 17 | type Person = { 18 | surname: string; 19 | middleName?: string; 20 | givenName: string; 21 | }; 22 | type ReadonlyPerson = Readonly; 23 | // ^? 24 | ``` 25 | 26 | 上の`ReadonlyPerson`は次の型と同じになります。 27 | 28 | ```ts twoslash 29 | type ReadonlyPerson = { 30 | readonly surname: string; 31 | readonly middleName?: string; 32 | readonly givenName: string; 33 | }; 34 | ``` 35 | 36 | ## Readonlyの効果は再帰的ではない 37 | 38 | `Readonly`が読み取り専用にするのは、オブジェクトの型`T`直下のプロパティのみです。プロパティがオブジェクトだった場合、それが持つプロパティまでは読み取り専用にならないので注意してください。 39 | 40 | ## Readonlyの実装 41 | 42 | `Readonly`は次のように実装されています。 43 | 44 | ```ts twoslash 45 | // @noErrors: 2300 46 | type Readonly = { 47 | readonly [P in keyof T]: T[P]; 48 | }; 49 | ``` 50 | 51 | ## 関連情報 52 | 53 | [オブジェクト型のreadonlyプロパティ (readonly property)](../../values-types-variables/object/readonly-property.md) 54 | 55 | [クラスのreadonly修飾子](../../object-oriented/class/readonly-modifier-in-classes.md) 56 | 57 | [インターフェースのreadonly修飾子](../../object-oriented/interface/readonly-modifier-in-interfaces.md) 58 | 59 | [readonlyとconstの違い](../../values-types-variables/object/readonly-vs-const.md) 60 | -------------------------------------------------------------------------------- /docs/reference/type-reuse/utility-types/record.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: キー・バリューからオブジェクト型を作る 3 | title: "Record" 4 | --- 5 | 6 | `Record`はプロパティのキーが`Keys`であり、プロパティの値が`Type`であるオブジェクトの型を作るユーティリティ型です。 7 | 8 | ## Record<Keys, Type>の型引数 9 | 10 | ### Keys 11 | 12 | オブジェクトのプロパティーキーを指定します。`Keys`に代入できる型は、`string`、`number`、`symbol`とそれぞれのリテラル型です。 13 | 14 | ### Type 15 | 16 | オブジェクトのプロパティの値の型を指定します。任意の型が代入できます。 17 | 18 | ## Recordの使用例 19 | 20 | キーが`string`で値が`number`のインデックス型を定義する。 21 | 22 | ```ts twoslash 23 | type StringNumber = Record; 24 | const value: StringNumber = { a: 1, b: 2, c: 3 }; 25 | ``` 26 | 27 | キーが`firstName`、`middleName`、`familyName`で、値が文字列になるオブジェクトの型を定義する。 28 | 29 | ```ts twoslash 30 | type Person = Record<"firstName" | "middleName" | "lastName", string>; 31 | const person: Person = { 32 | firstName: "Robert", 33 | middleName: "Cecil", 34 | lastName: "Martin", 35 | }; 36 | ``` 37 | 38 | ## 関連情報 39 | 40 | [インデックス型 (index signature)](../../values-types-variables/object/index-signature.md) 41 | 42 | [マップ型 (Mapped Types)](../mapped-types.md) 43 | 44 | [Map](../../builtin-api/map.md) 45 | -------------------------------------------------------------------------------- /docs/reference/type-reuse/utility-types/required.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: 全プロパティを必須にする 3 | title: Required 4 | --- 5 | 6 | `Required`は、`T`のすべてのプロパティからオプショナルであることを意味する`?`を取り除くユーティリティ型です。 7 | 8 | ## Required<T>の型引数 9 | 10 | ### T 11 | 12 | 型引数`T`にはオブジェクトの型を表す型を代入します。 13 | 14 | ## Requiredの使用例 15 | 16 | ```ts twoslash 17 | type Person = { 18 | surname: string; 19 | middleName?: string; 20 | givenName: string; 21 | }; 22 | type RequiredPerson = Required; 23 | // ^? 24 | ``` 25 | 26 | 上の`RequiredPerson`は次と同じ型になります。 27 | 28 | ```ts twoslash 29 | type RequiredPerson = { 30 | surname: string; 31 | middleName: string; 32 | givenName: string; 33 | }; 34 | ``` 35 | 36 | ## Requiredの実装 37 | 38 | `Required`は次のように実装されています。 39 | 40 | ```ts twoslash 41 | // @noErrors: 2300 42 | type Required = { 43 | [P in keyof T]-?: T[P]; 44 | }; 45 | ``` 46 | 47 | `Partial`と参照してみると違いがわかります。 48 | 49 | ```ts twoslash 50 | // @noErrors: 2300 51 | type Partial = { 52 | [P in keyof T]?: T[P]; 53 | }; 54 | ``` 55 | 56 | 異なる部分は`-?`と`?`の部分です。`?`はオプション修飾子で、プロパティがオプショナルになります。`-?`はオプション修飾子を取り除くことを意味します。したがって、`Required`は、`T`のすべてのプロパティからオプショナルであることを意味する`?`を取り除いた型を生成します。 57 | このときの`-`をmapping modifierと呼びます。 58 | 59 | ## 関連情報 60 | 61 | [Partial<T>](partial.md) 62 | 63 | [Mapped Types](../mapped-types.md) 64 | -------------------------------------------------------------------------------- /docs/reference/type-reuse/utility-types/return-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: 関数の戻り値の型を取得する 3 | title: "ReturnType" 4 | --- 5 | 6 | `ReturnType`は、関数型`T`の戻り値を取得するユーティリティ型です。 7 | 8 | ## ReturnType<T>の型引数 9 | 10 | ### T 11 | 12 | 型引数`T`には、関数の型を渡します。 13 | 14 | ## ReturnTypeの使用例 15 | 16 | ```ts twoslash 17 | // @errors: 2344 18 | type ReturnType1 = ReturnType<() => string>; 19 | // ^? 20 | type ReturnType2 = ReturnType<(arg: string) => string | number>; 21 | // ^? 22 | type ReturnType3 = ReturnType<() => never>; 23 | // ^? 24 | ``` 25 | 26 | 多くは`typeof`と併用して実際の関数の戻り値を取得します。 27 | 28 | ```ts twoslash 29 | const isEven = (num: number) => { 30 | return num / 2 === 0; 31 | }; 32 | 33 | type isEvenRetType = ReturnType; 34 | // ^? 35 | ``` 36 | 37 | `ReturnType`は内部的には`infer`を使って実装されています。 38 | 39 | ```ts twoslash 40 | // @noErrors 41 | type ReturnType any> = T extends ( 42 | ...args: any 43 | ) => infer R 44 | ? R 45 | : any; 46 | ``` 47 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/array/array-as-a-object.md: -------------------------------------------------------------------------------- 1 | # 配列はオブジェクト 2 | 3 | JavaScriptの配列はオブジェクトです。そのため、比較やコピーの際の挙動に注意が必要です。 4 | 5 | ## 配列同士の比較 6 | 7 | 配列の中身が同じでも、オブジェクトのインスタンスが異なると`==`では期待する比較ができないので注意が必要です。 8 | 9 | ```ts twoslash 10 | const list1 = [1, 2, 3]; 11 | const list2 = [1, 2, 3]; 12 | console.log(list1 == list2); 13 | // @log: false 14 | ``` 15 | 16 | PHPでは配列(インデックス配列)は要素の内容で等価比較できますが、JavaScriptでは同じようにはできないので注意しましょう。 17 | 18 | ```php 19 | bool(true) 23 | ``` 24 | 25 | このような配列の中身を比べるための演算子やメソッドはJavaScriptにはないため、中身を比較したいときにはlodashの[isEqual](https://lodash.com/docs/4.17.15#isEqual)などのパッケージを使うのがお勧めです。 26 | 27 | ## 配列のコピー 28 | 29 | 配列も他のオブジェクトと同様に、代入を用いても値のコピーにはなりません。代入元の変数と代入先の変数は同じ値を指します。そして、一方の変数だけを変更したつもりでも、他方にも変更が反映されます。 30 | 31 | ```ts twoslash 32 | const arr = [1, 2, 3]; 33 | const backup = arr; 34 | arr.push(4); // 変更 35 | console.log(arr); 36 | // @log: (4) [1, 2, 3, 4] 37 | console.log(backup); // こちらにも影響 38 | // @log: (4) [1, 2, 3, 4] 39 | ``` 40 | 41 | 上のような単純な配列のコピーには、スプレッド構文を使ってください。 42 | 43 | ```ts twoslash 44 | const arr = [1, 2, 3]; 45 | const backup = [...arr]; // スプレッド構文 46 | arr.push(4); // 変更 47 | console.log(backup); // 影響なし 48 | // @log: (4) [1, 2, 3] 49 | ``` 50 | 51 | [配列のコピー](./spread-syntax-for-array.md) 52 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/array/array-literal.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 配列リテラル 3 | --- 4 | 5 | # 配列リテラル (array literal) 6 | 7 | JavaScriptでは配列を配列リテラル(array literal)で書けます。配列リテラルはブラケット(`[`、`]`)を用いて書きます。 8 | 9 | ```js twoslash 10 | [1, 2, 3]; 11 | ``` 12 | 13 | 配列リテラルは要素の区切れ目で改行して書くこともできます。最後の要素にはカンマを書いても構いません。 14 | 15 | 16 | ```js twoslash 17 | [ 18 | 1, 19 | 2, 20 | 3, 21 | ] 22 | ``` 23 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/array/type-annotation-of-array.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 配列の型注釈 3 | --- 4 | 5 | # 配列の型注釈 (type annotation) 6 | 7 | TypeScriptでは、配列に型注釈する方法が2通りあります。 8 | 9 | ## Type\[] 10 | 11 | 1つ目の型注釈は、要素の型の後ろに`[]`をつける書き方です。たとえば、number型の配列の型注釈は`number[]`と書きます。 12 | 13 | ```ts twoslash 14 | let array: number[]; 15 | array = [1, 2, 3]; 16 | ``` 17 | 18 | ## Array<T> 19 | 20 | 2つ目の型注釈は、`Array`を用いる書き方です。`T`には要素の型を書きます。たとえば、number型の配列の型注釈は`Array`と書きます。 21 | 22 | ```ts twoslash 23 | let array: Array; 24 | array = [1, 2, 3]; 25 | ``` 26 | 27 | ## Type\[]とArray<T>どちらを使うべきか? 28 | 29 | TypeScriptでの配列の型注釈は、`Type[]`と`Array`の2通りあるわけですが、その違いは書き方だけです。コード上の意味、つまり、コンパイラのチェックの内容はどちらも同じです。したがって、どちらの書き方を選ぶかは、書き手の好みになります。ただし、プロジェクトとしてはどちらの書き方にするかは統一しておくべきです。 30 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/bigint.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: bigint型 3 | title: bigint型(長整数型) 4 | --- 5 | 6 | JavaScriptのbigint型は、number型よりも大きな整数を扱えるプリミティブ型です。 7 | 8 | ## bigint型リテラル 9 | 10 | JavaScriptのbigint型のリテラルは整数値の末尾に`n`をつけて書きます。 11 | 12 | ```ts twoslash 13 | const x = 100n; 14 | ``` 15 | 16 | bigintリテラルをTypeScriptで用いるには、コンパイラーオプションのtargetをes2020以上にする必要があります。 17 | 18 | ## bigint型の型注釈 19 | 20 | TypeScriptでbigint型を型注釈するには、`bigint`を用います。 21 | 22 | ```ts twoslash 23 | const x: bigint = 100n; 24 | ``` 25 | 26 | ## BigInt関数 27 | 28 | bigint型はBigInt関数を使って作ることができます。BigInt関数は第1引数に数値もしくは文字列を渡します。 29 | 30 | ```ts twoslash 31 | const x = BigInt(100); 32 | const y = BigInt("9007199254740991"); 33 | ``` 34 | 35 | TypeScriptでBigInt関数を用いるには、コンパイラーオプションのlibをes2020以上にする必要があります。 36 | 37 | ## bigint型をnumber型と計算する 38 | 39 | bigint型とnumber型はそのままでは一緒に演算をすることはできません。どちらかに型を合わせる必要があります。 40 | 41 | ```ts twoslash 42 | // @errors: 2365 43 | 2n + 3; 44 | ``` 45 | 46 | number型が小数部を持っていない限り、より表現幅の広いbigint型に合わせる方が無難です。 47 | 48 | ```ts twoslash 49 | const i = 2n + BigInt(3); 50 | console.log(i); 51 | // @log: 5n 52 | ``` 53 | 54 | ## bigint型を使う上での注意点 55 | 56 | bigint型を直接`JSON.stringify()`に渡すと、TypeErrorが発生します。 57 | 58 | ```ts twoslash 59 | JSON.stringify(12n); 60 | // @error: TypeError: Do not know how to serialize a BigInt 61 | ``` 62 | 63 | また、bigint型を含むオブジェクトを`JSON.stringify()`に渡しても、TypeErrorが発生します。 64 | 65 | ```ts twoslash 66 | JSON.stringify({ x: 12n }); 67 | // @error: TypeError: Do not know how to serialize a BigInt 68 | ``` 69 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/boolean.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: boolean型 3 | title: boolean型 (論理型) 4 | --- 5 | 6 | JavaScriptのboolean型は、`true`と`false`の論理値からなる型です。 7 | 8 | ## boolean型リテラル 9 | 10 | JavaScriptのboolean型リテラルは`true`または`false`を用いて次のように書きます。 11 | 12 | ```ts twoslash 13 | const isOk = true; 14 | const isPanda = false; 15 | ``` 16 | 17 | ## boolean型の型注釈 18 | 19 | TypeScriptのboolean型の型注釈は`boolean`を使います。 20 | 21 | ```ts twoslash 22 | const isOk: boolean = true; 23 | ``` 24 | 25 | TypeScriptには大文字で始まる`Boolean`型がありますが、これと`boolean`は別の型です。 26 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/difference-between-type-inference-and-dynamic-typing.md: -------------------------------------------------------------------------------- 1 | # 型推論と動的型付けの違い 2 | 3 | 型を書かないという意味では、JavaScriptをはじめRubyやPHPなどの動的型付け言語でも同様です。型推論と動的型付けは何が違うのでしょうか? 4 | 5 | 型推論はコンパイルのタイミングで型が決定され、その型が変更されることはありません。型をプログラマが書くかコンパイラが自動で決めるという点で違いがあり、あくまで静的型付けの世界に閉じた話になります。 6 | 7 | 次のTypeScriptの例では、変数`x`が型推論により`number`型として決定され、以降は常に`number`型として振舞います。 8 | 9 | ```ts twoslash title="TypeScript" 10 | // @errors: 2322 2339 11 | let x = 1; 12 | // ^? 13 | x = "hello"; // xはnumber型と決定しているのでstring型を代入するとエラー 14 | console.log(x.substring(1, 3)); 15 | ``` 16 | 17 | 一方、動的型付けでは実行時に型が決まるので、実行タイミングにより型が変化します。次のJavaScriptの例では、最初に`1`の値が代入され変数`x`の型は`number`型となります。その後、`hello`の文字列を代入することで 変数`x`の型は`string`型に変更されます。このように実行タイミングで型が変化するので、型推論ではエラーになる処理も動的型付け言語では正常に動作します。 18 | 19 | ```ts title="JavaScript" twoslash 20 | let x = 1; // xはnumber型となる 21 | x = "hello"; //x はstring型となる 22 | console.log(x.substring(1, 3)); 23 | // @log: "el" 24 | // @noErrors 25 | ``` 26 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/enum/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 列挙型 3 | slug: /reference/values-types-variables/enum 4 | --- 5 | 6 | # 列挙型 (enum) 7 | 8 | TypeScriptでは、列挙型(enum)を用いると、定数のセットに意味を持たせたコード表現ができます。 9 | 10 | 列挙型を宣言するには、`enum`キーワードの後に列挙型名とメンバーを書きます。次の例では、`Position`が列挙型名で、`Top`、`Right`、`Bottom`、`Left`がメンバーになります。 11 | 12 | ```ts twoslash 13 | enum Position { 14 | Top, 15 | Right, 16 | Bottom, 17 | Left, 18 | } 19 | ``` 20 | 21 | `enum`キーワードはTypeScript独自のものです。なのでJavaScriptにコンパイルすると次のようなコードになります。 22 | 23 | 24 | ```js 25 | var Position; 26 | (function (Position) { 27 | Position[Position["Top"] = 0] = "Top"; 28 | Position[Position["Right"] = 1] = "Right"; 29 | Position[Position["Bottom"] = 2] = "Bottom"; 30 | Position[Position["Left"] = 3] = "Left"; 31 | })(Position || (Position = {})); 32 | ``` 33 | 34 | ご覧のとおり、列挙型名と同じ名前のオブジェクトが定義されます。列挙型のメンバーはオブジェクトのプロパティーになります。値は0からの連番になります。 35 | 36 | ```ts twoslash 37 | enum Position { 38 | Top, 39 | Right, 40 | Bottom, 41 | Left, 42 | } 43 | // ---cut--- 44 | console.log(Position.Top); // 0 45 | console.log(Position.Right); // 1 46 | console.log(Position.Bottom); // 2 47 | ``` 48 | 49 | 列挙型名は型として扱うことができます。 50 | 51 | ```ts twoslash 52 | enum Position { 53 | Top, 54 | Right, 55 | Bottom, 56 | Left, 57 | } 58 | // ---cut--- 59 | let position: Position; 60 | // ^^^^^^^^型 61 | ``` 62 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/enum/numeric-enum.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 数値列挙型 3 | --- 4 | 5 | # 数値列挙型 (numeric enum) 6 | 7 | TypeScriptの数値列挙型(numeric enum)はもっとも典型的な列挙型です。メンバーの値は上から順に`0`からの連番になります。 8 | 9 | ```ts twoslash 10 | enum Position { 11 | Top, // 0 12 | Right, // 1 13 | Bottom, // 2 14 | Left, // 3 15 | } 16 | ``` 17 | 18 | メンバーは値を代入できます。値を代入した場合、それに続くメンバーは連番になります。 19 | 20 | ```ts twoslash 21 | enum Position { 22 | Top = 1, // 1 23 | Right, // 2 24 | Bottom, // 3 25 | Left, // 4 26 | } 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/enum/string-enum.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 文字列列挙型 3 | --- 4 | 5 | # 文字列列挙型 (string enum) 6 | 7 | TypeScriptの列挙型では、メンバーの値に文字列も使えます。文字列で構成された列挙型は文字列列挙型(string enum)と呼ばれます。 8 | 9 | ```ts twoslash 10 | enum Direction { 11 | Up = "UP", 12 | Down = "DOWN", 13 | Left = "LEFT", 14 | Right = "RIGHT", 15 | } 16 | ``` 17 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/let-and-const.md: -------------------------------------------------------------------------------- 1 | # 変数宣言: letとconst 2 | 3 | JavaScriptの変数宣言(variable declaration)には、`let`と`const`があります。 4 | 5 | ## letの変数宣言 6 | 7 | `let`を用いた変数宣言の書き方は次のようにします。 8 | 9 | ```ts twoslash 10 | let x = 1; 11 | ``` 12 | 13 | `let`は再代入が可能です。 14 | 15 | ```ts twoslash 16 | let x = 1; 17 | x = 2; // 再代入ができる 18 | ``` 19 | 20 | `let`は変数の初期値なしで変数定義できます。初期値なしの変数の値は`undefined`になります。 21 | 22 | ```js twoslash 23 | let x; // 初期値なし 24 | x = 1; // 後で代入 25 | ``` 26 | 27 | ## constの変数宣言 28 | 29 | `const`を用いた変数宣言の書き方は次のようになります。初期値は必須です。 30 | 31 | ```js twoslash 32 | const y = 2; 33 | ``` 34 | 35 | `const`は変数への再代入が禁止されています。 36 | 37 | ```js twoslash 38 | const y = 1; 39 | y = 1; 40 | // @error: TypeError: Assignment to constant variable. 41 | ``` 42 | 43 | ## letとconstの使い分け 44 | 45 | 初めて JavaScript を書く場合に、`let`と`const`のどちらの変数宣言を使えばよいか悩む場合があるかもしれません。基本は`const`で変数宣言をして必要な場合にのみ、`let`を使うのがオススメです。`const`で変数宣言することで再代入を禁止して、意図せず変数が書き換えられることを予防できるので、より安全なコードになります。 46 | 47 | 48 | 49 | ・JavaScriptの変数宣言はletとconstがある 50 | ・letは再代入OK、constは再代入NG 51 | ・基本的にconstを使うとよい 52 | 53 | 54 | 55 | ## constは可変オブジェクトを保護しない 56 | 57 | constは再代入不可な変数名を宣言するだけです。constには、可変(ミュータブル)なオブジェクトのプロパティを不変にする保護効果はありません。この点は誤解されがちです。 58 | 59 | たとえば、constでオブジェクトを宣言した場合、変数自体への再代入はできません。ところが、オブジェクトプロパティは変更できます。 60 | 61 | ```ts twoslash 62 | // @errors: 2588 63 | const obj = { a: 1 }; 64 | obj = { a: 2 }; // 再代入は不可 65 | obj.a = 2; // プロパティの変更はできる 66 | ``` 67 | 68 | TypeScriptでオブジェクトを不変にするには、プロパティを読み取り専用にする必要があります。 69 | 70 | [readonlyプロパティ](./object/readonly-property.md) 71 | 72 | 配列もオブジェクトの一種なので同様です。変数自体の再代入はできません。しかし、配列要素は変更できます。 73 | 74 | ```ts twoslash 75 | // @errors: 2588 76 | const arr = [1, 2]; 77 | arr = [3, 4]; // 再代入は不可 78 | arr.push(3); // 要素の変更はできる 79 | ``` 80 | 81 | TypeScriptで配列を不変にするには読み取り専用配列を使う必要があります。 82 | 83 | [読み取り専用配列](./array/readonly-array.md) 84 | 85 | constアサーションを使ってオブジェクトや配列を不変にする方法もあります。 86 | 87 | [constアサーション](./const-assertion.md) 88 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/literal-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: リテラル型 3 | --- 4 | 5 | # リテラル型 (literal type) 6 | 7 | TypeScriptではプリミティブ型の特定の値だけを代入可能にする型を表現できます。そのような型をリテラル型と呼びます。 8 | 9 | たとえば、次の例は数値が代入可能な型注釈です。数値であれば、1でも100でも何でも代入できます。 10 | 11 | ```ts twoslash 12 | let x: number; 13 | x = 1; 14 | ``` 15 | 16 | リテラル型を用いると、1だけが代入可能な型が作れます。 17 | 18 | ```ts twoslash 19 | // @errors: 2322 20 | let x: 1; 21 | x = 1; 22 | x = 100; 23 | ``` 24 | 25 | ## リテラル型として表現できるもの 26 | 27 | リテラル型として表現できるプリミティブ型は次のとおりです。 28 | 29 | - boolean型のtrueとfalse 30 | - number型の値 31 | - string型の文字列 32 | 33 | ```ts twoslash 34 | const isTrue: true = true; 35 | const num: 123 = 123; 36 | const str: "foo" = "foo"; 37 | ``` 38 | 39 | ## リテラル型の用途 40 | 41 | 一般的にリテラル型はマジックナンバーやステートの表現に用いられます。その際、ユニオン型と組み合わせることが多いです。 42 | 43 | ```ts twoslash 44 | let num: 1 | 2 | 3 = 1; 45 | ``` 46 | 47 | [ユニオン型 (union type)](union.md) 48 | 49 | [判別可能なユニオン (discriminated union)](discriminated-union.md) 50 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/null.md: -------------------------------------------------------------------------------- 1 | # null型 2 | 3 | JavaScriptのnullは値がないことを示す値です。 4 | 5 | ## nullリテラル 6 | 7 | JavaScriptのnullリテラルは`null`です。 8 | 9 | ```ts twoslash 10 | const x = null; 11 | ``` 12 | 13 | ## nullの型注釈 14 | 15 | TypeScriptでnull型を型注釈するには`null`を用います。 16 | 17 | ```ts twoslash 18 | const x: null = null; 19 | ``` 20 | 21 | ## typeof演算子の注意点 22 | 23 | JavaScriptには値の型を調べるtypeof演算子があります。`null`に対して`typeof`を用いると`"object"`が返るので注意が必要です。 24 | 25 | ```ts twoslash 26 | console.log(typeof null); 27 | // @log: "object" 28 | ``` 29 | 30 | typeof演算子の詳細は「typeof演算子」のセクションをご覧ください。 31 | 32 | [typeof演算子 (typeof operator)](typeof-operator.md) 33 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/number/decimal-calculation-error.md: -------------------------------------------------------------------------------- 1 | # 小数計算の誤差 2 | 3 | JavaScriptの小数の計算には誤差が生じる場合があるので要注意です。たとえば、0.1 + 0.2は0.3になってほしいところですが、計算結果は0.30000000000000004になります。これはJavaScriptのバグではありません。 4 | 5 | ```js 6 | 0.1 + 0.2 === 0.3; //=> false 7 | ``` 8 | 9 | number型はIEEE 754という規格に準拠していて、その制約によって生じる現象です。10進数の0.2は有限小数ですが、それを2進数で表すと0.0011...のような循環小数になります。循環小数は小数点以下が無限に続きますが、IEEE 754が扱う小数点以下は有限であるため、循環小数は桁の途中で切り捨てられます。その結果、小数の計算に誤差が生じてしまうわけです。これはちょうど、私達が円周率の計算を筆算するときの制約に似ています。円周率は3.141592...と無限に小数点以下が続きますが、時間も紙面も有限なため、ある程度の誤差は妥協して3.14に丸めて計算するかと思います。ちなみに、2進数で有限小数になる0.5や0.25などの数値だけを扱う計算は誤差なく計算できます。 10 | 11 | ```js 12 | 0.5 + 0.25 === 0.75; //=> true 13 | ``` 14 | 15 | 小数計算の誤差を解決するために、一度整数に桁上げして計算し、もとの桁を下げる方法が考えられます。整数の計算は誤差が生じないという特性に期待した方法です。たとえば、110円の消費税込価格を求める計算を考えてみましょう。110に1.1を掛け算すると、誤差が生じて121円ぴったりにはなりません。 16 | 17 | ```js 18 | 110 * 1.1; //=> 121.00000000000001 19 | ``` 20 | 21 | そこで、110と桁上げした税率11を掛け算してから、10で割ってみます。すると、うまく計算できます。 22 | 23 | ```js 24 | (110 * 11) / 10 === 121; //=> true 25 | ``` 26 | 27 | この方法を使う場合は、桁を戻した数値は小数になることがあり、その値には小数計算誤差問題が残り続けることに注意してください。 28 | 29 | ```js twoslash 30 | const price1 = (101 * 11) / 10; // 111.1 31 | const price2 = (103 * 11) / 10; // 113.3 32 | price1 + price2; // 224.39999999999998 33 | ``` 34 | 35 | 小数計算の誤差問題を包括的に解決したい場合は、[decimal.js](https://github.com/MikeMcl/decimal.js/)のような計算誤差がないパッケージを使うのも手です。 36 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/object/difference-among-object-and-object/image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/reference/values-types-variables/object/difference-among-object-and-object/image1.png -------------------------------------------------------------------------------- /docs/reference/values-types-variables/object/excess-property-checking.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 余剰プロパティチェック 3 | --- 4 | 5 | # 余剰プロパティチェック (excess property checking) 6 | 7 | TypeScriptのオブジェクトの型には余剰プロパティチェック(excess property checking)という、追加のチェックが働く場合があります。余剰プロパティチェックとは、オブジェクトの型に存在しないプロパティを持つオブジェクトの代入を禁止する検査です。 8 | 9 | たとえば、`{ x: number }`はプロパティ`x`が必須なオブジェクトの型です。この型に`{ x: 1, y: 2 }`のような値を代入しようとします。この代入は許可されるでしょうか。代入値の型は、必須プロパティの`{ x: number }`を満たしているので問題なさそうです。ところが、この代入は許可されません。 10 | 11 | ```ts twoslash 12 | // @errors: 2353 13 | let onlyX: { x: number }; 14 | onlyX = { x: 1 }; // OK 15 | onlyX = { x: 1, y: 2 }; // コンパイルエラー 16 | ``` 17 | 18 | このとき、「Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; }'.」というコンパイルエラーが発生します。なぜこれがコンパイルエラーになるかというと、`{ y: 2 }`が余計だと判断されるからです。こうした余計なプロパティを許さないTypeScriptのチェックが余剰プロパティチェックなのです。 19 | 20 | ## 余剰プロパティチェックはオブジェクトリテラルだけを検査する 21 | 22 | 余剰プロパティチェックはオブジェクトの余計なプロパティを禁止するため、コードが型に厳密になるよう手助けをします。しかし、余剰プロパティチェックが効くのは、オブジェクトリテラルの代入に対してのみです。なので、変数代入にはこのチェックは働きません。 23 | 24 | ```ts twoslash 25 | const xy: { x: number; y: number } = { x: 1, y: 2 }; 26 | let onlyX: { x: number }; 27 | onlyX = xy; // OK 28 | ``` 29 | 30 | 変数代入にも余剰プロパティチェックが働いたほうが良さそうと思われるかもしれません。型が厳密になるからです。しかし、そうなっていないのは、TypeScriptが型の安全性よりも利便性を優先しているためです。 31 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/object/index-signature.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: インデックス型 3 | --- 4 | 5 | # インデックス型 (index signature) 6 | 7 | TypeScriptで、オブジェクトのフィールド名をあえて指定せず、プロパティのみを指定したい場合があります。そのときに使えるのがこのインデックス型(index signature)です。たとえば、プロパティがすべて`number`型であるオブジェクトは次のように型注釈します。 8 | 9 | ```ts twoslash 10 | let obj: { 11 | [K: string]: number; 12 | }; 13 | ``` 14 | 15 | フィールド名の表現部分が`[K: string]`です。この`K`の部分は型変数です。任意の型変数名にできます。`K`や`key`にするのが一般的です。`string`の部分はフィールド名の型を表します。インデックス型のフィールド名の型は`string`、`number`、`symbol`のみが指定できます。 16 | 17 | インデックス型のオブジェクトであれば、フィールド名が定義されていないプロパティも代入できます。たとえば、インデックス型`{ [K: string]: number }`には、値がnumber型であれば、`a`や`b`など定義されていないフィールドに代入できます。 18 | 19 | ```ts twoslash 20 | let obj: { 21 | [K: string]: number; 22 | }; 23 | 24 | obj = { a: 1, b: 2 }; // OK 25 | obj.c = 4; // OK 26 | obj["d"] = 5; // OK 27 | ``` 28 | 29 | コンパイラーオプションの`noUncheckedIndexedAccess`を有効にした場合、インデックス型では、プロパティの型は自動的にプロパティに指定した型とundefined型のユニオン型になります。これは、プロパティが存在しないときに、値が`undefined`になるのを正確に型で表すためです。 30 | 31 | ```ts twoslash 32 | const obj: { [K: string]: number } = { a: 1 }; 33 | const b: number | undefined = obj.b; 34 | console.log(b); 35 | // @log: undefined 36 | ``` 37 | 38 | [noUncheckedIndexedAccess](../../tsconfig/nouncheckedindexedaccess.md) 39 | 40 | ## Record<K, T>を用いたインデックス型 41 | 42 | インデックス型は`Record`ユーティリティ型を用いても表現できます。次の2つの型注釈は同じ意味になります。 43 | 44 | ```ts twoslash 45 | let obj1: { [K: string]: number }; 46 | let obj2: Record; 47 | ``` 48 | 49 | [Record<Keys, Type>](../../type-reuse/utility-types/record.md) 50 | 51 | ## 関連情報 52 | 53 | [Mapped Types](../../type-reuse/mapped-types.md) 54 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/object/non-primitives-are-objects.md: -------------------------------------------------------------------------------- 1 | # プリミティブ以外はすべてオブジェクト 2 | 3 | JavaScriptでは、プリミティブ型以外のものはすべてオブジェクトです。オブジェクトには、クラスから作ったインスタンスだけでなく、クラスそのものや配列、正規表現もあります。 4 | 5 | プリミティブ型は値が同じであれば、同一のものと判定できますが、オブジェクトはプロパティの値が同じであっても、インスタンスが異なると同一のものとは判定されません。 6 | 7 | ```js twoslash 8 | const value1 = 123; 9 | const value2 = 123; 10 | console.log(value1 == value2); 11 | // @log: true 12 | 13 | const object1 = { value: 123 }; 14 | const object2 = { value: 123 }; 15 | console.log(object1 == object2); 16 | // @log: false 17 | ``` 18 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/object/object-literal.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: オブジェクトリテラル 3 | --- 4 | 5 | # オブジェクトリテラル (object literal) 6 | 7 | JavaScriptの特徴はオブジェクトリテラル`{}`という記法を用いて、簡単にオブジェクトを生成できる点です。 8 | 9 | ```js twoslash 10 | // 空っぽのオブジェクトを生成 11 | const object = {}; 12 | 13 | // プロパティを指定しながらオブジェクトを生成 14 | const person = { name: "Bob", age: 25 }; 15 | ``` 16 | 17 | JavaやPHPなどの言語では、オブジェクトを生成するにはまずクラスを定義し、そのクラスを元にインスタンスを作るのが普通ですが、JavaScriptはクラス定義がなくてもこのようにオブジェクトリテラルを書くと、オブジェクトをインラインで作れます。 18 | 19 | オブジェクトリテラルがあるおかげで、JavaScriptでは自由度の高いコードが書けるようになっています。 20 | 21 | 次の例のように、JavaScriptでも`Object`を`new`することでオブジェクトを作ることができます。しかし、オブジェクトリテラルを使ったほうが端的で読みやすいコードになります。 22 | 23 | ```js twoslash 24 | const person = new Object(); 25 | person.name = "Bob"; 26 | person.age = 25; 27 | ``` 28 | 29 | ちなみに、広く使われるデータシリアライズ形式にJSONがあるのはご存知でしょう。JSONは多くのプログラミング言語で用いられていますが、JSONはJavaScript Object Notationの略で、JSONの由来はJavaScriptのオブジェクトリテラルにあります。そして、JavaScriptではJSONをそのままオブジェクトリテラルとして解釈できます。 30 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/object/optional-property.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: オブジェクト型のオプションプロパティ 3 | --- 4 | 5 | # オブジェクトの型のオプションプロパティ (optional property) 6 | 7 | TypeScriptで、オブジェクトプロパティのオプショナルを型付けするには、プロパティ名の後ろに`?`を書きます。 8 | 9 | ```ts twoslash 10 | type Size = { 11 | width?: number; 12 | }; 13 | ``` 14 | 15 | オプションプロパティを持ったオブジェクトの型には、そのオプションプロパティを持たないオブジェクトを代入できます。 16 | 17 | ```ts twoslash 18 | type Size = { 19 | width?: number; 20 | }; 21 | // ---cut--- 22 | const size: Size = {}; // OK 23 | ``` 24 | 25 | また、オプションプロパティの値が`undefined`のオブジェクトも代入できます。 26 | 27 | ```ts twoslash 28 | type Size = { 29 | width?: number; 30 | }; 31 | // ---cut--- 32 | const size: Size = { 33 | width: undefined, 34 | }; // OK 35 | ``` 36 | 37 | しかし、オプションプロパティの値が`null`の場合は代入できません。 38 | 39 | ```ts twoslash 40 | // @errors: 2322 41 | type Size = { 42 | width?: number; 43 | }; 44 | // ---cut--- 45 | const size: Size = { 46 | width: null, 47 | }; 48 | ``` 49 | 50 | ただし`strictNullChecks`を無効にしている場合は`null`も代入できるようになります。 51 | 52 | ```ts twoslash title="strictNullChecksがfalseの場合" 53 | // @strictNullChecks: false 54 | type Size = { 55 | width?: number; 56 | }; 57 | // ---cut--- 58 | const size: Size = { 59 | width: null, 60 | }; 61 | ``` 62 | 63 | ## 関連情報 64 | 65 | [オプショナルチェーン (optional chaining)](optional-chaining.md) 66 | 67 | [strictNullChecks](../../../reference/tsconfig/strictnullchecks.md) 68 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/object/properties-of-objects.md: -------------------------------------------------------------------------------- 1 | # オブジェクトのプロパティ 2 | 3 | JavaScriptのオブジェクトは、プロパティの集合体です。プロパティはキーと値の対です。プロパティの値には、`1`や`"string"`のようなプリミティブ型や関数、そして、オブジェクトも入れることができます。 4 | 5 | ```js twoslash 6 | const product = { 7 | name: "ミネラルウォーター", 8 | price: 100, 9 | getTaxIncludedPrice: function () { 10 | return Math.floor(this.price * 1.1); 11 | }, 12 | shomikigen: new Date("2022-01-20"), 13 | }; 14 | ``` 15 | 16 | 上の`getTaxIncludedPrice`には関数が代入されていますが、この関数は「メソッド」と呼ばれます。メソッドとは、オブジェクトに関連づいた関数のことです。メソッドを定義するには、キーと関数の値に分けて書く方法だけでなく、メソッド定義のための短い構文を使うこともできます。 17 | 18 | ```js twoslash 19 | const object = { 20 | // キーと値に分けて書いたメソッド定義 21 | printHello1: function () { 22 | console.log("Hello"); 23 | }, 24 | // 短い構文を用いたメソッド定義 25 | printHello2() { 26 | console.log("Hello"); 27 | }, 28 | }; 29 | ``` 30 | 31 | JavaやPHPでは、オブジェクトのフィールドとメソッドははっきり区別されます。一方、JavaScriptではその区別はきっちりしていません。Javaで言うところのメソッドとフィールドは、JavaScriptでは同じように扱われます。たとえば、メソッドに`null`を代入することで、フィールドに変えてしまうこともできます。 32 | 33 | ```js twoslash 34 | const calculator = { 35 | sum(a, b) { 36 | return a + b; 37 | }, 38 | }; 39 | 40 | calculator.sum(1, 1); 41 | // @log: 2 42 | calculator.sum = null; 43 | calculator.sum(1, 1); // ここではもうメソッドではないので、呼び出すとエラーになります 44 | ``` 45 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/object/readonly-vs-const.md: -------------------------------------------------------------------------------- 1 | # readonlyとconstの違い 2 | 3 | JavaScriptでは、`const`で宣言した変数は代入不可になります。TypeScriptではオブジェクトの型のプロパティに`readonly`修飾子をつけると、そのプロパティが代入不可になります。これら2つの機能は「代入不可」という点では似ています。ではこれらの違いは何でしょうか。 4 | 5 | ## constは変数への代入を禁止にするもの 6 | 7 | `const`は変数への代入を禁止するものです。たとえば、`const`で宣言されたxに値を代入しようとすると、TypeScriptではコンパイルエラーになり、JavaScriptでは実行時エラーになります。 8 | 9 | ```ts twoslash 10 | // @errors: 2588 11 | const x = 1; 12 | x = 2; 13 | ``` 14 | 15 | `const`の代入禁止が効くのは変数そのものへの代入だけです。変数がオブジェクトだった場合、プロパティへの代入は許可されます。 16 | 17 | ```ts twoslash 18 | // @errors: 2588 19 | const x = { y: 1 }; 20 | x = { y: 2 }; // 変数そのものへの代入は不可 21 | x.y = 2; // プロパティへの代入は許可 22 | ``` 23 | 24 | ## readonlyはプロパティへの代入を禁止にするもの 25 | 26 | TypeScriptの`readonly`はプロパティへの代入を禁止するものです。たとえば、`readonly`がついたプロパティxに値を代入しようとすると、コンパイルエラーになります。 27 | 28 | ```ts twoslash 29 | // @errors: 2540 30 | let obj: { readonly x: number } = { x: 1 }; 31 | obj.x = 2; 32 | ``` 33 | 34 | 一方、変数自体への代入は許可されます。 35 | 36 | ```ts twoslash 37 | let obj: { readonly x: number } = { x: 1 }; 38 | obj = { x: 2 }; // 許可される 39 | ``` 40 | 41 | ## constとreadonlyの違い 42 | 43 | `const`は変数自体を代入不可するものです。変数がオブジェクトの場合、プロパティへの代入は許可されます。一方、`readonly`はプロパティを代入不可にするものです。変数自体を置き換えるような代入は許可されます。以上の違いがあるため、`const`と`readonly`を組み合わせると、変数自体とオブジェクトのプロパティの両方を変更不能なオブジェクトを作ることができます。 44 | 45 | ```ts twoslash 46 | // @errors: 2588 2540 47 | const obj: { readonly x: number } = { x: 1 }; 48 | obj = { x: 2 }; 49 | obj.x = 2; 50 | ``` 51 | 52 | ## 関連情報 53 | 54 | [変数宣言: letとconst](../let-and-const.md) 55 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/object/shorthand-property-names.md: -------------------------------------------------------------------------------- 1 | # Shorthand property names 2 | 3 | オブジェクトのキーと変数名が同じ時にかぎり、オブジェクトに値を代入するときも同様にShorthand property namesを使うことができます。これも分割代入と調べると情報を得られることがあります。次の例がほぼすべてです。 4 | 5 | ```ts twoslash 6 | import fs from "fs"; 7 | // ---cut--- 8 | type Wild = { 9 | name: string; 10 | no: number; 11 | genre: string; 12 | height: number; 13 | weight: number; 14 | }; 15 | 16 | const name = "pikachu"; 17 | const no = 25; 18 | const genre = "mouse pokémon"; 19 | const height = 0.4; 20 | const weight = 6.0; 21 | 22 | const pikachu: Wild = { 23 | name, 24 | no, 25 | genre, 26 | height, 27 | weight, 28 | }; 29 | ``` 30 | 31 | 要するにこちらの省略型です。 32 | 33 | ```ts twoslash 34 | import fs from "fs"; 35 | 36 | type Wild = { 37 | name: string; 38 | no: number; 39 | genre: string; 40 | height: number; 41 | weight: number; 42 | }; 43 | 44 | const name = "pikachu"; 45 | const no = 25; 46 | const genre = "mouse pokémon"; 47 | const height = 0.4; 48 | const weight = 6.0; 49 | // ---cut--- 50 | const pikachu: Wild = { 51 | name: name, 52 | no: no, 53 | genre: genre, 54 | height: height, 55 | weight: weight, 56 | }; 57 | ``` 58 | 59 | もちろん一行で書くこともできます。 60 | 61 | ```ts twoslash 62 | import fs from "fs"; 63 | 64 | type Wild = { 65 | name: string; 66 | no: number; 67 | genre: string; 68 | height: number; 69 | weight: number; 70 | }; 71 | 72 | const name = "pikachu"; 73 | const no = 25; 74 | const genre = "mouse pokémon"; 75 | const height = 0.4; 76 | const weight = 6.0; 77 | // ---cut--- 78 | const pikachu: Wild = { name, no, genre, height, weight }; 79 | ``` 80 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/primitive-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: プリミティブ型 3 | --- 4 | 5 | # プリミティブ型 (primitive types) 6 | 7 | JavaScriptのデータ型は、プリミティブ型とオブジェクトの2つに分類されます。 8 | 9 | ## イミュータブル特性 10 | 11 | JavaScriptのプリミティブ型の1つ目の特徴は、値を直接変更できない点です。つまりイミュータブル(immutable)です。一方、オブジェクトには、値を後で変更できるというミュータブル特性(mutable)があります。 12 | 13 | ## プロパティを持たない 14 | 15 | JavaScriptのプリミティブ型の2つ目の特徴は、基本的にプロパティがないことです。プリミティブ型の`null`と`undefined`にはプロパティがありません。 16 | 17 | ```js 18 | null.toString(); // エラーになる 19 | ``` 20 | 21 | ところが、文字列や数値などのプリミティブ型は、プロパティを持ったオブジェクトとして扱えます。 22 | 23 | ```js 24 | "name".length; // 4 25 | ``` 26 | 27 | このように、プリミティブ型をまるでオブジェクトのように扱えるのはJavaScriptの特徴です。JavaScriptには、プリミティブ型をオブジェクトに自動変換する機能があります。この機能はオートボクシング(autoboxing)、自動ボックス化と呼ばれます。 28 | 29 | [ボックス化 (boxing)](boxing.md) 30 | 31 | ## プリミティブ型の種類 32 | 33 | プリミティブ型は次の7つがあります。 34 | 35 | 36 | 37 | 1. boolean型(論理型): `true`または`false`の真偽値。 38 | 2. number型(数値型): `0`や`0.1`のような数値。 39 | 3. string型(文字列型): `"Hello World"`のような文字列。 40 | 4. undefined型: 値が未定義であることを表す型。 41 | 5. null型: 値がないことを表す型。 42 | 6. symbol型(シンボル型): 一意で不変の値。 43 | 7. bigint型(長整数型): `9007199254740992n`のようなnumber型では扱えない大きな整数型。 44 | 45 | 46 | 上のプリミティブ型以外は、JavaScriptにおいてはすべてオブジェクトと考えて問題ありません。配列や正規表現オブジェクトなどもすべてオブジェクトです。 47 | 48 | 49 | 50 | ・JSのプリミティブ型はイミュータブルでプロパティを持たない 51 | ・プリミティブをオブジェクトのように扱える「オートボクシング」がある 52 | ・プリミティブは7種類: boolean, number, string, undefined, null, symbol, bigint 53 | ・それ以外は全部オブジェクト 54 | 55 | 56 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/symbol.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: symbol型 3 | title: symbol型 (シンボル型) 4 | --- 5 | 6 | JavaScriptのsymbol型はプリミティブ型の一種で、その値が一意になる値です。boolean型やnumber型は値が同じであれば、等価比較が`true`になります。一方、シンボルはシンボル名が同じであっても、初期化した場所が違うと`false`になります。 7 | 8 | ```js twoslash 9 | const s1 = Symbol("foo"); 10 | const s2 = Symbol("foo"); 11 | console.log(s1 === s1); 12 | // @log: true 13 | console.log(s1 === s2); 14 | // @log: false 15 | ``` 16 | 17 | Rubyにもシンボルという名前の型があります。Rubyのシンボルは値さえ同じなら、書いてある場所が異なっても等価比較が`true`になります。 18 | 19 | ```ruby 20 | # Rubyコード 21 | s1 = :foo 22 | s2 = :foo 23 | p s1 == s2 #=> true 24 | ``` 25 | 26 | 一方、JavaScriptでは前述のとおり、シンボルを初期化した場所で決まるので、Rubyから来た方は注意してください。Rubyのシンボル的なことは、JavaScriptやTypeScriptでは文字列を用いて解決します。 27 | 28 | ## シンボルの型注釈 29 | 30 | TypeScriptでシンボルの型注釈は`symbol`を用います。 31 | 32 | ```ts twoslash 33 | const s: symbol = Symbol(); 34 | ``` 35 | 36 | ## symbol型を使う上での注意点 37 | 38 | symbol型を直接`JSON.stringify()`に渡すと`undefined`が返ります。 39 | 40 | ```ts twoslash 41 | console.log(JSON.stringify(Symbol("many"))); 42 | // @log: undefined 43 | ``` 44 | 45 | また、symbol型をプロパティに含むオブジェクトを`JSON.stringify()`に渡すと、symbol型をプロパティに含むキーは消滅します。 46 | 47 | ```ts twoslash 48 | console.log( 49 | JSON.stringify({ 50 | x: Symbol("many"), 51 | y: "hello", 52 | }) 53 | ); 54 | // @log: { "y": "hello" } 55 | ``` 56 | 57 | 同様に、symbol型をキーに含むオブジェクトを`JSON.stringify()`に渡すと、symbol型のキーは消滅します。 58 | 59 | ```ts twoslash 60 | console.log( 61 | JSON.stringify({ 62 | [Symbol("many")]: "hello", 63 | y: "hello", 64 | }) 65 | ); 66 | // @log: { "y": "hello" } 67 | ``` 68 | 69 | ## シンボルの用途 70 | 71 | JavaScriptにシンボルが導入された動機は、JavaScriptの組み込みAPIの下位互換性を壊さずに新たなAPIを追加することでした。要するに、JavaScript本体をアップデートしやすくするために導入されたものです。したがって、アプリケーションを開発する場合に限っては、シンボルを駆使してコードを書く機会はそう多くはありません。 72 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/type-alias.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 型エイリアス 3 | --- 4 | 5 | # 型エイリアス (type alias) 6 | 7 | TypeScriptでは、型に名前をつけられます。名前のついた型を型エイリアス(タイプエイリアス; type alias)と呼びます。 8 | 9 | ## 型エイリアスの宣言 10 | 11 | 型エイリアスを宣言するには`type`キーワードを使います。次の例は、`string | number`型に`StringOrNumber`という型名を名付けたものです。 12 | 13 | ```ts twoslash 14 | type StringOrNumber = string | number; 15 | ``` 16 | 17 | 型エイリアスは、`string`などのビルトインの型と同様に、変数や引数、戻り値の型注釈などで使えます。 18 | 19 | ```ts twoslash 20 | type StringOrNumber = string | number; 21 | // ---cut--- 22 | const value: StringOrNumber = 123; 23 | ``` 24 | 25 | ## 型エイリアスの使用例 26 | 27 | 型エイリアスはさまざまな型に名前をつけられます。型エイリアスの一例を次に示します。 28 | 29 | ```ts twoslash 30 | // プリミティブ型 31 | type Str = string; 32 | // リテラル型 33 | type OK = 200; 34 | // 配列型 35 | type Numbers = number[]; 36 | // オブジェクト型 37 | type UserObject = { id: number; name: string }; 38 | // ユニオン型 39 | type NumberOrNull = number | null; 40 | // 関数型 41 | type CallbackFunction = (value: string) => boolean; 42 | ``` 43 | 44 | ## 型エイリアスの使い道 45 | 46 | 型エイリアスは同じ型を再利用したいときに使うと便利です。型の定義が一箇所になるため、保守性が向上します。 47 | 48 | また、型に名前を与えることで可読性が上がる場合があります。型に名前があると、その型が何を意味しているのかがコードの読み手に伝わりやすくなります。 49 | 50 | ## 関連情報 51 | 52 | [🚧interfaceとtypeの違い](../object-oriented/interface/interface-vs-type-alias.md) 53 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/type-annotation.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 変数宣言の型注釈 3 | --- 4 | 5 | # 変数宣言の型注釈 (type annotation) 6 | 7 | TypeScriptでは変数宣言するときに、その変数にどんな値が代入可能かを指定できます。その指定のことを型注釈(type annotation; 型アノテーション)と言います。変数宣言の型注釈は、次のように変数名の右に型を書きます。 8 | 9 | ```ts twoslash 10 | const num: number = 123; 11 | // ^^^^^^^^ 型注釈 12 | ``` 13 | 14 | Javaなどの言語も変数に対して型を宣言できますが、変数名と型を書く位置は左右逆です。これらの言語に慣れている方は注意してください。 15 | 16 | ```java 17 | Int num = 123; // Java 18 | ``` 19 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/type-coercion.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 型強制 3 | --- 4 | 5 | # 型強制 (type coercion) 6 | 7 | JavaScriptにはデータ型がありますが、型が異なる2つの値に対し演算してもエラーにならない場合があります。たとえば、string型の`"1"`からnumber型の`1`を減算した場合、number型の`0`が計算結果として出てきます。 8 | 9 | ```js 10 | "1" - 1; //=> 0 11 | ``` 12 | 13 | これは型強制(type coercion)と呼ばれる仕組みがあるためです。型強制とは、型が異なる2つの値を処理するとき、暗黙的に別の型へ変換されることを言います。 14 | 15 | 上の例では、string型の`"1"`がnumber型の`1`に型強制された上で、`- 1`が演算されたため`0`が計算結果になるわけです。 16 | 17 | 型に厳しい言語では、型が異なる値同士の演算ができない言語もあるので、そのような言語に慣れている方は特に注意してください。 18 | 19 | ちなみに、どんな型に型強制されるかは演算子によっても異なるので注意が必要です。たとえば、string型の`"1"`にnumber型の`1`を加算する場合は、string型の`"11"`が計算結果になります。これは、number型の`1`がstring型の`"1"`に型強制された上で、`"1" + "1"`の文字列結合の演算になるためです。 20 | 21 | ```js 22 | "1" + 1; //=> "11" 23 | ``` 24 | 25 | 26 | 27 | 文字列と数値など型が異なる2つの値を演算するとき、暗黙に型変換される「型強制」がJavaScriptにはある。 28 | 29 | "1" - 1; //=> 0 30 | "1" + 1; //=> "11" 31 | 32 | 33 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/type-inference.md: -------------------------------------------------------------------------------- 1 | # 変数宣言の型推論 2 | 3 | TypeScriptには型推論(type inference)と呼ばれる機能があります。型推論は、**コンパイラが型を自動で判別する機能**です。プログラマーは型推論を活用すると、型注釈を省略できるので、コードの記述量を減らせる利点があります。 4 | 5 | ```ts twoslash 6 | // @errors: 2322 7 | let x = 1; // let x: number = 1;と同じ意味になる 8 | x = "hello"; 9 | ``` 10 | 11 | 上の例では変数`x`に`1`の値コードを代入しています。この時点でコンパイラは代入された値から、変数`x`の型を`number`型と自動で判別します。型注釈`x: number`を書くことを省略できます。 12 | 13 | 型注釈が書かれていないものの`x`は`number`型を推論されているため、`x`に`hello`のstring型を再代入する記述は、型の不一致によりコンパイルエラーとなります。 14 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/undefined.md: -------------------------------------------------------------------------------- 1 | # undefined型 2 | 3 | JavaScriptのundefinedは未定義を表すプリミティブな値です。変数に値がセットされていないとき、戻り値が無い関数、オブジェクトに存在しないプロパティにアクセスしたとき、配列に存在しないインデックスでアクセスしたときなどに現れます。 4 | 5 | ```js twoslash 6 | let name; 7 | console.log(name); 8 | // @log: undefined 9 | 10 | function func() {} 11 | console.log(func()); 12 | // @log: undefined 13 | 14 | const obj = {}; 15 | console.log(obj.name); 16 | // @log: undefined 17 | 18 | const arr = []; 19 | console.log(arr[1]); 20 | // @log: undefined 21 | ``` 22 | 23 | ## undefinedリテラル 24 | 25 | JavaScriptでは同じプリミティブ型でも、boolean型やnumber型がリテラルがあるのに対し、`undefined`にはリテラルはありません。実は`undefined`は変数です。グローバル定数のようなものと理解して構いません。 26 | 27 | ## undefinedの型注釈 28 | 29 | TypeScriptでundefined型の型注釈を行うには、`undefined`を用います。 30 | 31 | ```ts twoslash 32 | const x: undefined = undefined; 33 | ``` 34 | 35 | 戻り値のない関数は`undefined`になりますが、TypeScriptで戻り値なしを型注釈で表現する場合、`undefined`ではなく`void`を用います。詳しくは関数の説明をご覧ください。 36 | 37 | [戻り値がない関数とvoid型 (void type)](../functions/void-type.md) 38 | -------------------------------------------------------------------------------- /docs/reference/values-types-variables/union.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: ユニオン型 3 | --- 4 | 5 | # ユニオン型 (union type) 6 | 7 | TypeScriptのユニオン型(union type)は「いずれかの型」を表現するものです。 8 | 9 | ## ユニオン型の型注釈 10 | 11 | ユニオン型の型注釈は、2つ以上の型をパイプ記号(`|`)で繋げて書きます。たとえば、number型もしくはundefined型を表す場合は、`number | undefined`のように書きます。 12 | 13 | ```ts twoslash 14 | let numberOrUndefined: number | undefined; 15 | ``` 16 | 17 | `|`は型のリストの冒頭に置くこともできます。型ごとに改行するときに、列が揃うので便利です。 18 | 19 | 20 | ```ts twoslash 21 | type ErrorCode = 22 | | 400 23 | | 401 24 | | 402 25 | | 403 26 | | 404 27 | | 405; 28 | ``` 29 | 30 | ## 配列要素にユニオン型を使う際の書き方 31 | 32 | 配列の要素としてユニオン型を用いる場合は、書き方に注意が必要です。たとえば、`string`または`number`からなる配列の型を宣言することを考えてみましょう。`string`または`number`をユニオン型で表現すると`string | number`になります。配列型は要素の型に`[]`をつけて表現します。これをそのまま繋げて考えると、次のような型を思いつくかもしれませんが、これは間違いです。 33 | 34 | ```ts twoslash 35 | type List = string | number[]; 36 | ``` 37 | 38 | これは`string`型または`number[]`型であることになっているためです。正しくは以下です。特に配列を`T[]`形式で書いているときは`()`が必要になるので注意してください。 39 | 40 | ```ts twoslash 41 | type List = (string | number)[]; 42 | ``` 43 | 44 | ## ユニオン型と絞り込み 45 | 46 | ユニオン型`string | null`が`string`なのか`null`なのかを判定したいときは、TypeScriptの絞り込み(narrowing)を用います。絞り込みをするにはいくつかの方法がありますが、代表例はif文です。条件分岐で変数がstring型かどうかをチェックすると、同じ変数でも分岐内では`string | null`型が`string`型だと判定されます。 47 | 48 | ```ts twoslash 49 | // @errors: 2322 50 | const maybeUserId: string | null = localStorage.getItem("userId"); 51 | 52 | const userId: string = maybeUserId; // nullかもしれないので、代入できない。 53 | 54 | if (typeof maybeUserId === "string") { 55 | const userId: string = maybeUserId; // この分岐内では文字列型に絞り込まれるため、代入できる。 56 | } 57 | ``` 58 | 59 | [制御フロー分析と型ガードによる型の絞り込み](../statements/control-flow-analysis-and-type-guard.md) 60 | 61 | ## 関連情報 62 | 63 | [判別可能なユニオン (discriminated union)](discriminated-union.md) 64 | -------------------------------------------------------------------------------- /docs/tips/companion-object.md: -------------------------------------------------------------------------------- 1 | # コンパニオンオブジェクトパターン 2 | 3 | TypeScriptでは値と型に同名を与えてその両方を区別なく使うことができるテクニックがあります。これをコンパニオンオブジェクトと呼びます。 4 | これは、クラスを作るほどでもなけどそれっぽいファクトリーメソッドとオブジェクトが欲しいときに重宝します。 5 | 6 | ## コンパニオンオブジェクト (Companion Object) 7 | 8 | 次の例は長方形 (Rectangle) を作成するためのメソッド`from()`をもつオブジェクト`Rectangle`とその生成されるオブジェクトの型`Rectangle`です。これらの名称は衝突することなく定義ができ、外部から呼び出したときは同名で使用できます。 9 | 10 | 次の型と値 (ファクトリーメソッドを持つオブジェクト) は同じファイル`rectangle.ts`に存在するとします。 11 | 12 | ```ts twoslash 13 | export type Rectangle = { 14 | height: number; 15 | width: number; 16 | }; 17 | 18 | export const Rectangle = { 19 | from(height: number, width: number): Rectangle { 20 | return { 21 | height, 22 | width, 23 | }; 24 | }, 25 | }; 26 | ``` 27 | 28 | 値も型も同名で定義します。これを外部から import してみます。 29 | 30 | ```ts twoslash 31 | // @filename: rectangle.ts 32 | export type Rectangle = { 33 | height: number; 34 | width: number; 35 | }; 36 | 37 | export const Rectangle = { 38 | from(height: number, width: number): Rectangle { 39 | return { 40 | height, 41 | width, 42 | }; 43 | }, 44 | }; 45 | // @filename: index.ts 46 | // ---cut--- 47 | import { Rectangle } from "./rectangle"; 48 | 49 | const rec: Rectangle = Rectangle.from(1, 3); 50 | 51 | console.log(rec.height); 52 | // @log: 1 53 | console.log(rec.width); 54 | // @log: 3 55 | ``` 56 | 57 | このように import の部分は`Rectangle`のみとなり見通しもつきやすいという特徴があります。ちなみに`Rectangle.from()`のRectangleが値であり`const rec: Rectangle`のRectangleが型です。このようにTypeScriptでは同名の値と型を同時に使うことができます。 58 | -------------------------------------------------------------------------------- /docs/tips/generates-type-from-object-key.md: -------------------------------------------------------------------------------- 1 | # オブジェクトからキーの型を生成する 2 | 3 | ## オブジェクトからキーだけ欲しい 4 | 5 | あるメッセージが言語ごとに定義されているとします。 6 | 7 | ```ts twoslash 8 | const conf = { 9 | en: "Are you sure?", 10 | fr: "Êtes-vous sûr?", 11 | es: "Está seguro?", 12 | ja: "よろしいですか?", 13 | zh: "您确定吗?", 14 | }; 15 | ``` 16 | 17 | 内容は確認を促す変哲もないシステムのメッセージです。このオブジェクトを使ってシステムがサポートしている言語の一覧を作ります。次のようなユニオン型が今回の目的です。 18 | 19 | ```ts twoslash 20 | type Language = "en" | "fr" | "es" | "ja" | "zh"; 21 | ``` 22 | 23 | ### `typeof` 24 | 25 | 頻出するこの`typeof`はJavaScriptのものではなく、TypeScriptの`typeof`です。これをオブジェクトに対して使用している例は前のページにあるとおりです。 26 | 27 | [オブジェクトから型を生成する](generates-type-from-object.md) 28 | 29 | この例で実行すれば次のような型`TypeOfLanguage`が生成されるでしょう (型名は便宜的なものです) 。 30 | 31 | ```ts twoslash 32 | const conf = { 33 | en: "Are you sure?", 34 | fr: "Êtes-vous sûr?", 35 | es: "Está seguro?", 36 | ja: "よろしいですか?", 37 | zh: "您确定吗?", 38 | }; 39 | // ---cut--- 40 | type TypeOfLanguage = typeof conf; 41 | // ^? 42 | ``` 43 | 44 | ここまでくればあとは少しです。`TypeOfLanguage`型のキーだけを型にしてしまいます。 45 | 46 | ### `keyof` 47 | 48 | `keyof`はオブジェクトの型に使うとそのオブジェクトのキーをユニオン型にして返します。上記の`TypeOfLanguage`型があれば 49 | 50 | ```ts twoslash 51 | const conf = { 52 | en: "Are you sure?", 53 | fr: "Êtes-vous sûr?", 54 | es: "Está seguro?", 55 | ja: "よろしいですか?", 56 | zh: "您确定吗?", 57 | }; 58 | type TypeOfLanguage = typeof conf; 59 | // ---cut--- 60 | type Language = keyof TypeOfLanguage; 61 | // ^? 62 | ``` 63 | 64 | となります。 65 | 66 | [keyof型演算子](../reference/type-reuse/keyof-type-operator.md) 67 | 68 | ## まとめ 69 | 70 | 見た目が少々いびつですが、次でオブジェクトから希望するキーのユニオン型を生成できます。 71 | 72 | ```ts twoslash 73 | const conf = { 74 | en: "Are you sure?", 75 | fr: "Êtes-vous sûr?", 76 | es: "Está seguro?", 77 | ja: "よろしいですか?", 78 | zh: "您确定吗?", 79 | }; 80 | type TypeOfLanguage = typeof conf; 81 | // ---cut--- 82 | type Language = keyof typeof conf; 83 | // ^? 84 | ``` 85 | 86 | ### 疑問: `keyof conf`じゃダメなんですか? 87 | 88 | 動作しません。なぜなら`keyof`は値ではなく (オブジェクトの) 型に対して使用できるからです。一方`typeof`は値から型を生成するのでこの順番で使用する必要があります。 89 | -------------------------------------------------------------------------------- /docs/tips/generates-type-from-object.md: -------------------------------------------------------------------------------- 1 | # オブジェクトから型を生成する 2 | 3 | 多くの言語では型による構造体、オブジェクトの定義をしてからコーディングが始まりますが、元がJavaScriptであるTypeScriptにはそのような決まりがないことも多々あります。 4 | 5 | ## 一般的な型を先に決めるプログラミング 6 | 7 | 多くの言語ではその型が何かを決めてから、その型に属するオブジェクトを決めます。次の例はTypeScriptの例ですが、他の言語に当てはめても問題なく受け入れられると思います。 8 | 9 | ```ts twoslash 10 | type Account = { 11 | accountName: string; 12 | password: string; 13 | age: number; 14 | plan: "Free" | "Standard" | "Premium"; 15 | }; 16 | 17 | const account: Account = { 18 | accountName: "yyts", 19 | password: "ccbyncsa30", 20 | age: 80, 21 | plan: "Standard", 22 | }; 23 | ``` 24 | 25 | すでにJavaScriptの資産があるプロジェクトにおいては表立って型などなく、そのため`Account`といった型は存在せず代入式の`const account`のみが存在していることでしょう。そんなときはこの`const account`をTypeScriptに変換してできるだけ近い形で型を作ることができます。 26 | 27 | ### `typeof` 28 | 29 | この`typeof`はJavaScriptのものではなく、TypeScriptの`typeof`です。これを実際に動作している変数に使ってみるとその変数をTypeScriptはどのような型と認識しているのかがわかります。 30 | 31 | ```ts twoslash 32 | const account = { 33 | accountName: "yyts", 34 | password: "ccbyncsa30", 35 | age: 80, 36 | plan: "Standard", 37 | }; 38 | 39 | type Account = typeof account; 40 | // ^? 41 | ``` 42 | 43 | `plan`が意図するユニオン型にはなりませんが、それなりに近い型を得ることができました。 44 | 45 | ### プロパティを定数値で取得したい場合 46 | 47 | プロパティを定数値で取得したい場合はオブジェクトに`as const`をつけます。 48 | 49 | ```ts twoslash 50 | const account = { 51 | accountName: "yyts", 52 | password: "ccbyncsa30", 53 | age: 80, 54 | plan: "Standard", 55 | } as const; 56 | 57 | type Account = typeof account; 58 | // ^? 59 | ``` 60 | 61 | ### 特定のプロパティだけを定数値で取得したい場合 62 | 63 | これでは型の制約が強力すぎて他の値が代入できないので、もう少し柔軟にします。たとえば`plan`だけがユニオン型になるようにしたければ`plan`の右に希望の型を書いてあげればそれでその型になります。 64 | 65 | ```ts twoslash 66 | const account = { 67 | accountName: "yyts", 68 | password: "ccbyncsa30", 69 | age: 80, 70 | plan: "Standard" as "Free" | "Standard" | "Premium", 71 | }; 72 | 73 | type Account = typeof account; 74 | // ^? 75 | ``` 76 | -------------------------------------------------------------------------------- /docs/tutorials/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: /tutorials 3 | --- 4 | 5 | # 作って学ぶTypeScript 6 | 7 | この章では、TypeScriptを使った実践的な開発の流れを学びます。次のチュートリアルを用意しています。 8 | 9 | - [開発環境の準備](./setup.md) 10 | - [簡単な関数を作ってみよう](./make-a-simple-function-via-cli.md) 11 | - [Reactでいいねボタンを作ろう](./react-like-button-tutorial.md) 12 | - [Next.jsで猫画像ジェネレーターを作ろう](./nextjs.md) 13 | - [Vercelにデプロイしてみよう](./vercel-deploy.md) 14 | - [Jestでテストを書こう](./jest.md) 15 | - [Reactコンポーネントのテストを書こう](./component-test.md) 16 | - [Prettierでコード整形を自動化しよう](./prettier.md) 17 | - [ESLintでコーディング規約を自動化しよう](./eslint.md) 18 | 19 | この章の目的は、「もし実務でTypeScriptを使ったらどんな開発になるのか?」について体験することです。この章を進めるにあたって、TypeScriptの知識はまだ無くても構いません。解説の手順どおりに進めることで、開発を追体験できるようになっています。 20 | 21 | この章でのTypeScriptについての解説は最小限です。チュートリアルを進めるにあたり、必要なものは解説します。しかし、言語の詳しい仕様については省いています。まずは具体的な開発を体験してください。TypeScriptがどんな雰囲気なのか感じ取った上で、より詳しい言語の仕様や機能について学びたくなったら、次の章の「読んで学ぶTypeScript」をお読みください。 22 | 23 | [読んで学ぶTypeScript](/reference/README) 24 | -------------------------------------------------------------------------------- /docs/tutorials/component-test/result_fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/tutorials/component-test/result_fail.png -------------------------------------------------------------------------------- /docs/tutorials/component-test/result_pass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/tutorials/component-test/result_pass.png -------------------------------------------------------------------------------- /docs/tutorials/component-test/result_pass2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/tutorials/component-test/result_pass2.png -------------------------------------------------------------------------------- /docs/tutorials/component-test/simpleButton.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/tutorials/component-test/simpleButton.gif -------------------------------------------------------------------------------- /docs/tutorials/husky.md: -------------------------------------------------------------------------------- 1 | # 🚧huskyでコミット前チェックを自動化しよう 2 | 3 | :::caution 4 | 5 | 執筆中 6 | 7 | huskyを導入しprettierやeslintをコミット時に実行できるようになるチュートリアルを書く。 8 | 9 | ::: 10 | -------------------------------------------------------------------------------- /docs/tutorials/react-like-button-tutorial/like1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/tutorials/react-like-button-tutorial/like1.png -------------------------------------------------------------------------------- /docs/tutorials/react-like-button-tutorial/like2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/tutorials/react-like-button-tutorial/like2.gif -------------------------------------------------------------------------------- /docs/tutorials/react-like-button-tutorial/screen1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/tutorials/react-like-button-tutorial/screen1.png -------------------------------------------------------------------------------- /docs/tutorials/react-like-button-tutorial/screen2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/tutorials/react-like-button-tutorial/screen2.png -------------------------------------------------------------------------------- /docs/tutorials/react-like-button-tutorial/screen3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/tutorials/react-like-button-tutorial/screen3.png -------------------------------------------------------------------------------- /docs/tutorials/react-like-button-tutorial/screen4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/tutorials/react-like-button-tutorial/screen4.png -------------------------------------------------------------------------------- /docs/tutorials/vercel-deploy/random-cat-preview-one-more-cat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/tutorials/vercel-deploy/random-cat-preview-one-more-cat.png -------------------------------------------------------------------------------- /docs/tutorials/vercel-deploy/vercel-dashboard-production-random-cat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/tutorials/vercel-deploy/vercel-dashboard-production-random-cat.png -------------------------------------------------------------------------------- /docs/tutorials/vercel-deploy/vercel-deploy-complete-random-cat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/tutorials/vercel-deploy/vercel-deploy-complete-random-cat.png -------------------------------------------------------------------------------- /docs/tutorials/vercel-deploy/vercel-github-checks-merge-ready.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/tutorials/vercel-deploy/vercel-github-checks-merge-ready.png -------------------------------------------------------------------------------- /docs/tutorials/vercel-deploy/vercel-github-pr-preview-comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/tutorials/vercel-deploy/vercel-github-pr-preview-comment.png -------------------------------------------------------------------------------- /docs/tutorials/vercel-deploy/vercel-import-github-random-cat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/tutorials/vercel-deploy/vercel-import-github-random-cat.png -------------------------------------------------------------------------------- /docs/tutorials/vercel-deploy/vercel-project-delete-confirmation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/tutorials/vercel-deploy/vercel-project-delete-confirmation.png -------------------------------------------------------------------------------- /docs/tutorials/vercel-deploy/vercel-project-settings-delete-random-cat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/tutorials/vercel-deploy/vercel-project-settings-delete-random-cat.png -------------------------------------------------------------------------------- /docs/tutorials/vercel-deploy/vercel-project-settings-random-cat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/tutorials/vercel-deploy/vercel-project-settings-random-cat.png -------------------------------------------------------------------------------- /docs/typescript.md: -------------------------------------------------------------------------------- 1 | # 🚧TypeScript超入門 〜10分でわかるTypeScriptの概要〜 2 | 3 | TODO: 忙しい人向けにTypeScriptのエッセンスがわかる長めのシングルページを作る。 4 | -------------------------------------------------------------------------------- /docs/writing/contributing.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: あなたが本書に貢献できること。 3 | --- 4 | 5 | # CONTRIBUTING 6 | 7 | 本書の執筆には、TypeScripterのための座談会「YYTypeScript」の参加者を中心に、オープンソース的に複数人のライターが参加しています。本書をお読み下さった読者の方も、執筆をはじめ、さまざまな方法で本プロジェクトに参画できます。このページでは、どのような参加方法があるのか説明します。 8 | 9 | ## 感想を伝える 10 | 11 | - 読んでの感想を教えて頂けると、執筆の参考になります。 12 | - ポジティブな感想はうれしいです。モチベーションが上がります。 13 | 14 | ## 分からないことを質問する 15 | 16 | - TypeScriptで分からないことを質問して頂けると、執筆のトピックを考えるのに役立ちます。 17 | - 読んだ上で生まれた疑問を質問して頂けると、内容の改善に役立ちます。 18 | - 質問は下記で受け付けています: 19 | - Twitter: @suin 20 | - Slack: 21 | - 執筆会に参加してもらって質問して頂いても構いません。 22 | 23 | ## SNSでシェアする 24 | 25 | - TwitterなどSNSでシェアして頂けるとうれしいです。 26 | 27 | ## 執筆会を見学する 28 | 29 | - 「見学」はもっとも簡単な参加形態です。まずは気軽に見に来てください。 30 | - 見学の際には「見学に来ました」とお伝えください。 31 | - 執筆会の開催スケジュールはconnpassをご確認ください。 32 | - 33 | 34 | ## 執筆する 35 | 36 | - 執筆はこのプロジェクトの中心的な活動です。 37 | - 執筆には、次のような活動があります: 38 | - 新規ページを書く 39 | - 既存ページを良くする 40 | - 誤字脱字の訂正 41 | - 内容の改善 42 | - 内容の追記 43 | - 既存ページにコメントする 44 | 45 | [はじめて執筆する方へ](getting-started.md) 46 | 47 | ### 執筆会Discordに参加する 48 | 49 | 執筆会にはDiscordがあります。 50 | 51 | こちらのURLから参加できます→ 52 | 53 | ## 意思決定に参加する 54 | 55 | 行動方針や執筆に当たっての取り決めなど、意思決定をしたい場合、次のいずれかの方法があります。 56 | 57 | - Discordで、雑談レベルで提案する。 58 | - PDRの提案を書き、共有する。 59 | - 執筆会に来て相談する。 60 | 61 | ### 意思決定プロセス 62 | 63 | しっかりとしたプロセスはまだありません。今の所ふわっと合意できれば決定します。 64 | -------------------------------------------------------------------------------- /docs/writing/file-structure.md: -------------------------------------------------------------------------------- 1 | # ファイル構成 2 | 3 | どこにどのようなファイルがあるかを説明します。 4 | 5 | このリポジトリのファイル構成は次のようになっています。 6 | 7 | ```tree 8 | ├── .markdownlint.yaml ... markdownlintの設定 9 | ├── .prettierrc ... prettierの設定 10 | ├── .textlintrc ... textlintの設定 11 | ├── docs/ ... ⭐️本書のコンテンツ(文書・画像) 12 | ├── docusaurus.config.js ... Docusaurusの設定 13 | ├── prh/ ... textlintのprhルールの定義 14 | ├── sidebars.js ... ⭐️サイドバー(目次)の設定 15 | ├── src/ ... Docusaurusを拡張するプログラムなど 16 | └── static/ ... Docusaurus用の静的ファイル 17 | ``` 18 | 19 | 執筆者が変更を加える上で重要になるのは、`docs`ディレクトリと`sidebars.js`です。 20 | -------------------------------------------------------------------------------- /docs/writing/getting-started.md: -------------------------------------------------------------------------------- 1 | # はじめて執筆する方へ 2 | 3 | 執筆に興味を持ってくださりありがとうございます!ここでは執筆にあたって知っておくべきことを説明します。 4 | 5 | ## 本書のターゲットを意識してください 6 | 7 | 「はじめに」の「誰に向けて書かれた本か?」に記載されている読者をイメージして、その人にとってちょうどよいレベル感を想像して書いてください。 8 | 9 | [はじめに](../README.md) 10 | 11 | まったくのプログラミング初心者はターゲットではないため、たとえば「変数とは」「関数とは」といった初級すぎるところは説明を割愛します。しかし、変数という概念は他のプログラミング言語で知っているが、JavaScriptの構文として変数宣言をどう書くかは知らない可能性があります。なので、プログラミング経験者をイメージしつつも、JavaScriptの知識は無いかもしれないプログラマーを想像してください。 12 | 13 | ## 文体・スタイルを周りに合わせてください 14 | 15 | 基本的な文体スタイルは次のページで定めています。 16 | 17 | [文体・スタイル](styles.md) 18 | 19 | ## 用語はできるだけ統一してください 20 | 21 | 22 | 23 | 用語の表記ゆれができるだけ起こらないよう注意してください。「サーバ」や「サーバー」、「インターフェイス」「インターフェース」など、できるだけ既存のものに統一してください。神経を尖らせず、意識できる範囲で構いません。後で誰かが見つけて修正できます。 24 | 25 | 26 | 27 | 英語の訳語は一定の決まりがあります: 28 | 29 | [日英対訳表](japanese-english-table.md) 30 | 31 | ## プルリクする前に話し合おう 32 | 33 | 本プロジェクトのコラボレーションは「プルリクする前に話し合おう」を原則としています。改善点が見つかってもすぐに着手せず、まずはissueにて話し合いを行う必要があります。詳しくは次のページをご覧ください。 34 | 35 | [チケット駆動](ticket-driven.md) 36 | 37 | ## 途中でも公開しましょう 38 | 39 | 書き途中でもプルリクエストして構いません。途中までの情報でも、情報ゼロよりは読者の役に立ちます。 40 | 41 | ## 環境構築からプルリクエストまでの流れ 42 | 43 | 具体的な環境構築からプルリクエストまでの流れは次のページをご覧ください。 44 | 45 | [環境構築からプルリクエストまでの流れ](how-to-change.md) 46 | -------------------------------------------------------------------------------- /docs/writing/japanese-english-table.md: -------------------------------------------------------------------------------- 1 | # 日英対訳表 2 | 3 | 本書では専門用語を翻訳するにあたって、次の訳語を採用します。 4 | 5 | 6 | 7 | - Type assertion 8 | - 型アサーション 9 | - Spread syntax 10 | - スプレッド構文 11 | - Generic 12 | - ジェネリクス 13 | - Template literal 14 | - テンプレートリテラル 15 | - Optional parameters 16 | - オプション引数 17 | - Default parameters 18 | - デフォルト引数 19 | - Rest parameters 20 | - 残余引数 21 | - Destructuring assignment 22 | - 分割代入 23 | - Index signature 24 | - インデックス型 25 | - Discriminated unions 26 | - 判別可能なユニオン型 27 | - Nullish coalescing operator 28 | - Null合体演算子 29 | - Type guard 30 | - 型ガード 31 | - User defined type guard 32 | - ユーザー定義の型ガード 33 | - Enum 34 | - 列挙型 35 | - Polyfill 36 | - ポリフィル 37 | - Mapped Types 38 | - Mapped Types 39 | - Deep Diveでは「マップ型」と訳している箇所もあるが、`Map`との曖昧さが出てしまう恐れがあるので和訳はしない。 40 | - Definite assignment assertion 41 | - 明確な割り当てアサーション 42 | - Declaration merging 43 | - 宣言マージ 44 | - Assertion functions 45 | - アーサーション関数 46 | - Type predicate 47 | - 型述語 48 | 49 | 50 | 51 | ## 日本語が不明 52 | -------------------------------------------------------------------------------- /docs/writing/pdr/0000-why-do-we-write-technical-books.md: -------------------------------------------------------------------------------- 1 | # 0000-なぜ私たちは技術書を書くのか? 2 | 3 | - ステータス: 採用 4 | - 決定者: reoring, suin, philomagi, kakiuchi 5 | - 更新日: 2019-12-13 6 | 7 | ## 背景: なぜTypeScriptの技術書を書くのか? 8 | 9 | TypeScriptコミュニティを盛り上げるには、今何をしたらもっともインパクトがあるのか?この疑問がTypeScriptの技術書を書きはじめる原点となる。 10 | 11 | reoring, suin, nouphetの3名は、2019年9月よりYYTypeScriptというイベントを主催してきた。YYTypeScriptは、プログラマーが集まってTypeScriptについての雑談をしながら、プログラマー同士の繋がりを築くことを主眼とした取り組みだ。TypeScriptコミュニティを盛り上げていきたいという考えのもと、このイベントが開催されてきた。さらに歴史をさかのぼると、YYTypeScriptの前進となるイベントに、YYPHPというイベントがあった。PHPerが集い雑談する交流会で、2年間に渡り100回開催された。 12 | 13 | YYPHPとYYTypeScriptを主催して感じたことは、PHPと比べて**TypeScriptのコミュニティは規模が小さい**という点だ。いざYYTypeScriptをやってみると、参加者はすぐに顔見知りばかりになり、コミュニティ規模の差は参加者なら肌感覚で感じるところであろう。それも当然で、PHPと比べると、TypeScriptのほうが新興の言語であり、歴史が違う。YYPHPが成功したのは、成熟したコミュニティの上で開催されたことによることが大きい。状況に即した行動が実を結んだと言える。 14 | 15 | では、TypeScriptにおける「状況に即した行動」は何なのだろうか?TypeScriptコミュニティは急激な成長段階にあり、TypeScriptの人気は衰えを知らない。今後、TypeScriptを使い出すプログラマーも増加することが予想される。**今やるべきは、将来的にTypeScriptプログラマーを増やし、彼らをサポートすること**だ。もちろん、YYTypeScriptのような交流会にも大きな意義があると考えられるが、それはコミュニティがもっと大きくなったときに大きな効果を発揮する。 16 | 17 | 今我々がすべき、インパクトを最大化する行動は、TypeScriptの技術書を書くことだ。執筆はコミュニティが成長途上であるタイミングだからこそ、やる意義が大きい。日本語で書かれたTypeScriptの技術書は、片手で数えるほどしかない。そんな中、新たに書を送り出すことの価値は計り知れない。我々の執筆活動は、TypeScriptを学ぼうとする個々のプログラマーを助けるだけでなく、引いてはコミュニティを伸ばす大きな原動力のひとつになると確信している。 18 | 19 | - 関連動画: [YYTypeScript#13 執筆会 - YouTube 6:45~11:50](https://youtu.be/zYiazS4h5e8?t=406) 20 | 21 | ## 決定事項 22 | 23 | TypeScriptの技術書を書く。なぜなら、 24 | 25 | - TypeScriptのコミュニティは成長途上で情報が必要とされているから。 26 | - TypeScriptの技術書が少なく、書くことに大きな意義があるから。 27 | - TypeScriptコミュニティの成長に寄与できるから。 28 | -------------------------------------------------------------------------------- /docs/writing/pdr/0001-write-with-gitbook.md: -------------------------------------------------------------------------------- 1 | # 0001-GitBookで執筆する 2 | 3 | :::danger 4 | 5 | このPDRは廃止されました。代わって次のPDRを採用します。 6 | 7 | [Docusaurusを採用する](0009-use-docusaurus.md) 8 | 9 | ::: 10 | 11 | - ステータス: 廃止 12 | - 決定者: reoring, suin, philomagi, kakiuchi 13 | - 更新日: 2021-10-20 14 | 15 | ## 解決する問題とその背景 16 | 17 | どのようなツールを使って執筆するか? 18 | 19 | ## 決定事項 20 | 21 | 執筆するに当たって、GitBookを採用する。なぜなら、 22 | 23 | - チームでの共同作業しやすいため。 24 | - すぐ始められるため。 25 | - 不特定多数の参加が想定されない初期の少人数のコラボレーションでは十分そうだから。 26 | 27 | ## 関連PDR 28 | 29 | [Docusaurusを採用する](0009-use-docusaurus.md) 30 | 31 | ## 関連情報 32 | 33 | - [GitBookからDocusaurusに移行してはどうか? · Discussion #38 · yytypescript/book](https://github.com/yytypescript/book/discussions/38) 34 | -------------------------------------------------------------------------------- /docs/writing/pdr/0002-iterative-writing-process.md: -------------------------------------------------------------------------------- 1 | # 0002-イテレーティブな執筆プロセス 2 | 3 | - ステータス: 採用 4 | - 決定者: reoring, suin, philomagi, kakiuchi 5 | - 更新日: 2019-12-13 6 | 7 | ## 解決する問題とその背景 8 | 9 | 読まれるコンテンツにしていくにはどうしたらいいか? 10 | 11 | ## 検討した選択肢 12 | 13 | - ウォータフォール的な手法 (書ききってからリリース) 14 | - イテレーティブな手法 (書きながらちょいちょいリリース) 15 | 16 | ## 決定事項 17 | 18 | イテレーティブな手法を採用する。この手法では、**全体をざっくり書いた上で**、次のステップを繰り返しながら、**漸進的に全体の内容を充実させていく**。 19 | 20 | 1. 書く 21 | 2. 公開する 22 | 3. 読者からフィードバックをもらう 23 | 4. どこを良くするか決める 24 | 25 | イテレーティブとインクリメンタルは区別する。 26 | 27 | ![イテレーティブな絵の書き方とインクリメンタルな絵の書き方](0002-iterative-writing-process/iterative-vs-incremental.jpg) 28 | 29 | イテレーティブに書くため、初期は内容が薄い本になることが想定されるが、執筆を繰り返していくことで、完成度を高めていく。 30 | 31 | フィードバックからは、次のような意思決定がなされる。 32 | 33 | - 次にどんなテーマについて書くか? 34 | - 既存のコンテンツを加筆すべきか? 35 | 36 | フィードバックには、読者からの疑問が含まれる。疑問に答えるようにコンテンツを編集する。 37 | 38 | ### 採用理由 39 | 40 | - 公開時は本が完成していることが理想的だが、その理想には多くの時間を要する。公開後「読まれない」となると、かけたコストだけ損失も大きくなる。そのような大失敗は避ける必要がある。 41 | - 需要のあるテーマから攻めることで、「本が役に立つ」状態を常時キープしやすくする。 42 | -------------------------------------------------------------------------------- /docs/writing/pdr/0002-iterative-writing-process/iterative-vs-incremental.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/docs/writing/pdr/0002-iterative-writing-process/iterative-vs-incremental.jpg -------------------------------------------------------------------------------- /docs/writing/pdr/0003-target-readers.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: 本書はどのような読者層を想定するか? 3 | --- 4 | 5 | # 0003-読者層 6 | 7 | - ステータス: 採用 8 | - 決定者: reoring, suin, philomagi, kakiuchi 9 | - 更新日: 2019-12-13 10 | 11 | ## 解決する問題とその背景 12 | 13 | 本書はどのような読者層を想定するか? 14 | 15 | ## 決定事項 16 | 17 | 読者層としては、TypeScript初心者ではあるが、プログラミング経験者を想定する。 18 | 19 | 初心者を対象とする理由: 20 | 21 | - 本書執筆の根底には、TypeScriptプログラマを増やすことで、コミュニティを大きくするという目的がある。TypeScript経験者のスキルアップに貢献するよりも、これからTypeScriptをはじめる人に向けて書いたほうが、目的達成に効果的だから。 22 | 23 | プログラミング経験者を対象とする理由: 24 | 25 | - [アンケートにより、95%のプログラマがTypeScriptを第二言語として習得する](https://twitter.com/suin/status/1195159863665422338)ことが分かったため。 26 | 27 | ### 読者ペルソナ 28 | 29 | - 変数とか関数とかはわかってるような人。 30 | - PHPやPythonなどの動的型付け言語を主に扱ってきており、型をそこまで意識してこなかった。 31 | 32 | ### 対象外となる読者 33 | 34 | 上記の読者層定義にしたがって、次のような読者は読者として想定しない。 35 | 36 | - いわゆる中上級者。TypeScriptに精通していたり、自信を持ってTypeScriptのコーディングができる。 37 | - いわゆるプログラミング入門者。変数や関数などプログラミングの基礎をまだ理解していなかったり、他の言語でもまだソフトウェアを開発した経験がない。 38 | -------------------------------------------------------------------------------- /docs/writing/pdr/0004-how-to-manage-article-status.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: 各ページのステータス管理方法について 3 | --- 4 | 5 | # 0004-各ページのステータス管理方法 6 | 7 | - ステータス:採用 8 | - 決定者: suin, reoring, nouphet 9 | - 更新日: 2020-01-31 10 | 11 | ## 解決する問題とその背景 12 | 13 | 列挙された目次に対してのアサイン方法や管理方法が未定。 14 | 15 | ## 検討した選択肢 16 | 17 | - Google Docsで管理 18 | - 各ページにて管理 19 | - GitHub Issuesで管理 20 | 21 | ## 決定事項 22 | 23 | Google Docsで管理を採用した。なぜなら、 24 | 25 | - 目次がGoogle Docs上で管理されているため 26 | - ステータスがリアルタイムで同期できるため 27 | - 現在の運用人数(<10)であれば問題なさそうなため 28 | 29 | ## 各選択肢のよい点と悪い点 30 | 31 | ### Google Docsで管理 32 | 33 | - Good: 一覧化が容易 34 | - Good: 目次を他のツールと同期する手間がない 35 | - Bad: 利用ツールが増え得る 36 | - Bad: スケールしない 37 | 38 | ### 各ページにて管理 39 | 40 | 別途管理ツールを導入せず、記事の各ページの先頭にステータスを表記、本文内に担当者を書く。 41 | 42 | - Good: 利用ツールが増えない 43 | - Bad: 大人数になった時にどうか 44 | - Bad: 対応期限でソートが難しい 45 | - Bad: **GitBookはマージするまで最新情報が伝わらないので難しい** 46 | 47 | ### GitHub Issuesで管理 48 | 49 | - Good: スケールしそう 50 | - Bad: 今今の人数だと手間のほうが多そう 51 | -------------------------------------------------------------------------------- /docs/writing/pdr/0006-use-desu-masu.md: -------------------------------------------------------------------------------- 1 | # 0006-語末には「です」「ます」(敬体)に統一する 2 | 3 | - ステータス: 採用 4 | - 提案者: suin 5 | - 決定者: suin, reoring, nouphet, fuubit, クロレ 6 | - 更新日: 2020-01-31 7 | 8 | ## 解決する問題とその背景 9 | 10 | 書籍としての一体感を出すために、語末表現は統一されているべきだが、それは「〜だ、〜である」(常体)にするか、「〜です、〜ます」(敬体)にするか? 11 | 12 | ## 検討した選択肢 13 | 14 | - 「〜だ、〜である」(常体) 15 | - 「〜です、〜ます」(敬体) 16 | 17 | ## 決定事項 18 | 19 | **語末表現には「〜です、〜ます」(敬体)を採用する**。なぜなら、理由は次のとおり。 20 | 21 | - 敬体を使っている技術書も多く、受け入れられていると言えるから。 22 | - 手順を説明するときに、常体だと命令口調になってしまい書きにくいから。 23 | -------------------------------------------------------------------------------- /docs/writing/pdr/0007-use-function-for-sample-code.md: -------------------------------------------------------------------------------- 1 | # 0007-関数定義のサンプルコードには極力functionを使う 2 | 3 | - ステータス: 採用 4 | - 提案者: suin 5 | - 決定者: suin, reoring, クロレ, jamashita 6 | - 更新日: 2020-02-21 7 | 8 | ## 解決する問題とその背景 9 | 10 | TypeScript/JavaScriptの関数定義のサンプルコードを示すとき、関数(function)でもアロー関数(arrow function)でもどちらでも解説に影響がないとき、どちらの書き方を優先して使ったらいいか? 11 | 12 | JavaScriptでは、関数を定義するとき、functionを使う方法と、arrow functionを使う方法の2つがある。どのような基準でどちらを使うか明確にしておくことで、ひとつの書籍としての一体感が出るとともに、読者の混乱を避けることができる。 13 | 14 | ## 決定事項 15 | 16 | **関数定義のサンプルコードには極力functionを使う**。その理由は、 17 | 18 | - functionのほうが関数であることが、読み手にとって読み取りやすいから。 19 | - TypeScript公式のハンドブックでfunctionのほうを使っているから。 20 | 21 | ただし、**arrow functionを使うべきところ、使わないと解説できないところは、arrow functionを使う**。たとえば、 22 | 23 | - 高階関数などが、thisへの参照を持ちたい場合。 24 | - arrow functionそのものについての説明をする場合。 25 | - フレームワークなどのしきたりでarrow functionのほうが現実でよく使われる場合。 26 | -------------------------------------------------------------------------------- /docs/writing/pdr/0008-prefer-type-alias-over-interface.md: -------------------------------------------------------------------------------- 1 | # 0008-サンプルコードではInterfaceよりType Aliasを優先して使う 2 | 3 | - ステータス: 採用 4 | - 提案者: suin, jamashita, t-yng, クロレ 5 | - 決定者: 同上 6 | - 更新日: 2020-03-27 7 | 8 | ## 解決する問題とその背景 9 | 10 | - 事実: TypeScriptでは、interfaceとtype aliasのどちらでもオブジェクトの型を定義できる。 11 | - 見解: 書籍のサンプルコードはどちらかに統一するのが好ましい。 12 | - 論点: サンプルコードにおいて、オブジェクトの型定義には、interfaceとtype aliasどちらを選択するか? 13 | 14 | ## 検討した選択肢 15 | 16 | - interface 17 | - type alias 18 | 19 | ## 決定事項 20 | 21 | - サンプルコードでオブジェクトの型定義を示す場合は、type aliasを優先して使う。 22 | - 理由: 理由は忘れたが、多数決的に決まった。 23 | - 例外: 次の目的でサンプルコードを示す場合は、interfaceを使ってもよい。 24 | - interface自体を説明する。 25 | - interfaceとtype aliasの同異を説明する。 26 | - classでインターフェースをimplementsする。 27 | -------------------------------------------------------------------------------- /docs/writing/pdr/0010-ticket-driven.md: -------------------------------------------------------------------------------- 1 | # 0010-チケット駆動の執筆 2 | 3 | - ステータス: 採用 4 | - 提案者: @suin 5 | - 参加者: @suin, @canalun, @jamashita 6 | - 更新日: 2023-02-24 7 | 8 | プルリクエストをマージしない場合、プルリクエスト作者の時間と労力が無駄になり、申し訳ないという問題がある。これを解決すべく、プルリクエストを作成する前に、issueで話し合うプロセスを採用します。 9 | 10 | ## 背景: コントリビューターの増加 11 | 12 | サバイバルTypeScriptのコントリビューターの増加に伴い、プルリクエストが増えてきました。プルリクエストの中には、マージされないものも出てきました。その理由として、本書の方向性と合わないといった理由が多いです。 13 | 14 | ## 課題1: 労力などがもったいない 15 | 16 | プルリクエストは、コントリビューターの時間・労力・才能が注ぎ込まれて作られます。そうした貢献を取り込まないことは、時間・労力・才能を無駄遣いすることに他なりません。これは、コントリビューターにとって望ましいことではないでしょう。 17 | 18 | ## 課題2: 断るのが心理的負担 19 | 20 | プルリクエストを断ることは、メンテナーにとっても難しいことです。プルリクエストの背後にある時間や労力について考えると、ひとことでは断れません。読者のことを考えるとマージすべきではないと思いつつも、コントリビューターのことを思うとマージしてあげたい。そんな板挟みもあります。そうした心理的負担は、メンテナーにとっての問題であり、執筆を進める上での抵抗にもなっています。 21 | 22 | ## 解決策: チケット駆動 23 | 24 | 上の課題を解決するのがチケット駆動です。「着手する前に話し合いましょう」というのが趣旨です。 25 | 26 | 着手する前に話し合うことで、上の課題が解決し、次のメリットがあります。 27 | 28 | - 本書の方向性とあったプルリクエストが生まれやすい 29 | - コントリビューターの時間・労力・才能の無駄遣いが減る 30 | - メンテナーの心理的負担が軽減される 31 | 32 | また副次的に次のようなメリットもあります。 33 | 34 | - 変更の経緯が追える。変更についてどのような議論がなされたのか、なぜ変更する必要があったのかなどを後の人が知れるようになります。 35 | 36 | ### もしもチケット駆動でないプルリクエストが作られた場合 37 | 38 | もしも議論をせずにプルリクエストが作られた場合は、次のプロセスを行います。 39 | 40 | - issueから始め直す。議論が必要そうであれば、issueからやり直す必要があります。 41 | - そのままマージする。議論が必要なく、取り込む必要性が自明なときはマージする。 42 | 43 | ただし、できるだけチケット駆動を崩すべきではないと思うので、issueから始め直すがデフォルトフローとなるようにします。 44 | 45 | また、issueなしにプルリクエストが作られた場合は、Closeされるリスクが高いことをドキュメントで注意喚起しておきます。 46 | 47 | ## 副解決策: PULL_REQUEST_TEMPLATE.mdの導入 48 | 49 | PULL_REQUEST_TEMPLATE.mdを用意しておき、チケット駆動で行っていることを旨をそれに含めておきます。こうすることで、プルリクエストを作成する際にその内容が表示されるため、新規参加者もチケット駆動に気づきやすくなります。この解決策は、課題1には効果が薄いですが、課題2への解決策にはなります。 50 | 51 | ## 補助策: GitHub Actionsで「Close {issue_number}」をチェックする 52 | 53 | GitHub Actionsでプルリクエストの本文にイシューを閉じる指示「Close {issue_number}」が含まれているかをチェックし、チケット駆動が原則として働く環境づくりをします。 54 | 55 | 使用するGitHub Action: https://github.com/marketplace/actions/verify-linked-issue 56 | 57 | いくらチケット駆動を謳っても、それを働きかける環境がないと形骸化しそうです。形骸化を防ぐためには、このGitHub Actionsが有効そうです。 58 | 59 | ## 関連PDR 60 | 61 | なし 62 | -------------------------------------------------------------------------------- /docs/writing/pdr/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: /writing/pdr 3 | --- 4 | 5 | # PDR 6 | 7 | PDRは**P**ublisher's **D**ecision **R**ecordの略で、これまでコミュニティがどんな意思決定をしたかを記録したものです。 8 | 9 | プロジェクトに後から参加した人にとって、本プロジェクトの方針や執筆に使うツール、文体、技術スタックなどが「どうしてそれが選ばれたのか?」「どのような経緯でそうなったのか?」といったことがわかりにくくなります。 10 | 11 | PDRはそのような「なぜ」への答えになるよう、決定したことだけでなく、背景と理由、そして検討した代替手段などについて書きます。 12 | 13 | ## 採用 14 | 15 | [0000-なぜ私たちは技術書を書くのか?](0000-why-do-we-write-technical-books.md) 16 | 17 | [0002-イテレーティブな執筆プロセス](0002-iterative-writing-process.md) 18 | 19 | [0003-読者層](0003-target-readers.md) 20 | 21 | [0004-各ページのステータス管理方法](0004-how-to-manage-article-status.md) 22 | 23 | [0005-ライセンスについて](0005-about-license.md) 24 | 25 | [0006-語末には「です」「ます」(敬体)に統一する](0006-use-desu-masu.md) 26 | 27 | [0007-関数定義のサンプルコードには極力functionを使う](0007-use-function-for-sample-code.md) 28 | 29 | [0008-サンプルコードではInterfaceよりType Aliasを優先して使う](0008-prefer-type-alias-over-interface.md) 30 | 31 | [0009-Docusaurusを採用する](0009-use-docusaurus.md) 32 | 33 | ## 廃止 34 | 35 | [0001-GitBookで執筆する](0001-write-with-gitbook.md) 36 | 37 | ## テンプレート 38 | 39 | PDRを追加する際は、[PDRのテンプレート](pdr-template.md)をお使いください。 40 | -------------------------------------------------------------------------------- /docs/writing/pdr/pdr-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: PDRを書くための雛形です。 3 | --- 4 | 5 | # - 6 | 7 | - ステータス: 8 | - 提案者: 9 | - 参加者: 10 | - 更新日: 11 | 12 | 13 | 14 | 15 | 16 | ## 検討した選択肢 17 | 18 | 1. 19 | 1. 20 | 1. 21 | 22 | ## 各選択肢のよい点と悪い点 23 | 24 | ### 候補1: 25 | 26 | 27 | 28 | - Good: 29 | - Good: 30 | - Bad: 31 | - Bad: 32 | 33 | ### 候補2: 34 | 35 | 36 | 37 | - Good: 38 | - Good: 39 | - Bad: 40 | - Bad: 41 | 42 | ### 候補3: 43 | 44 | 45 | 46 | - Good: 47 | - Good: 48 | - Bad: 49 | - Bad: 50 | 51 | ## 関連PDR 52 | 53 | 54 | -------------------------------------------------------------------------------- /docs/writing/styles.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: みんなで執筆しても同じような文体になるようにするためのガイドラインです。 3 | --- 4 | 5 | # 文体・スタイル 6 | 7 | ## 文体 8 | 9 | ### 語末は敬体を使う 10 | 11 | > 🙆🏻‍♂️ 開発にはNode.jsが必要になり**ます**。 12 | > ❌ 開発にはNode.jsが必要に**なる**。 13 | > 🙆🏻‍♂️ TypeScriptはオープンソース**です**。 14 | > ❌ TypeScriptはオープンソース**である**。 15 | 16 | ## マークアップ 17 | 18 | ### プログラムにはコード記法を使い、それ以外には使わない 19 | 20 | > 🙆🏻‍♂️ この`new`演算子は、/ ❌ このnew演算子は、 21 | > 🙆🏻‍♂️ nullable coalescing operatorと呼ばれます。 22 | > ❌ `nullable coalescing operator`と呼ばれます。 23 | > 🙆🏻‍♂️ 強調するためにcode記法を使ってはいけません。 24 | > ❌ 強調するために`code記法`を使ってはいけません。 25 | 26 | ## Capitalization 27 | 28 | ### 英単語は小文字にする 29 | 30 | > 🙆🏻‍♂️ リテラル型(literal type)とは、 31 | > ❌ リテラル型(**L**iteral **T**ype)とは、 32 | 33 | ### 単数形を用いる 34 | 35 | > 🙆🏻‍♂️ プロパティ(property)とは、 36 | > ❌ プロパティ(propert**ies**)とは、 37 | 38 | ### 固有名詞は本家の表記に習う 39 | 40 | > 🙆🏻‍♂️ JavaScript / ❌ Javascript / ❌ javascript 41 | -------------------------------------------------------------------------------- /docs/writing/vscode.md: -------------------------------------------------------------------------------- 1 | # VS Codeで編集する 2 | 3 | Markdownファイルを編集するエディターはVS Codeがお勧めです。 4 | 5 | ## 推奨プラグイン 6 | 7 | 執筆者が導入すると便利なVS Codeプラグインです。 8 | 9 | ### textlintプラグイン 10 | 11 | [textlintプラグイン](https://marketplace.visualstudio.com/items?itemName=taichi.vscode-textlint)をインストールすると、修正が必要な箇所がわかりやすくなります。 12 | 13 | ### markdownlintプラグイン 14 | 15 | [markdownlint](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint)プラグインをインストールすると、修正が必要な箇所がわかりやすくなります。 16 | 17 | ### twoslashプラグイン 18 | 19 | [twoslashプラグイン](https://marketplace.visualstudio.com/items?itemName=Orta.vscode-twoslash)をインストールすると、twoslashの補完が効くようになります。 20 | 21 | ### Speechプラグイン 22 | 23 | [Speechプラグイン](https://marketplace.visualstudio.com/items?itemName=bierner.speech)は、選択したテキストを音声読み上げします。文章の音声読み上げを聞きながら、文章を確認すると、誤字などに気づける場合があります。 24 | 25 | ### Code Spell Checkerプラグイン 26 | 27 | [Code Spell Checkerプラグイン](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker)は英単語のスペルミスと思われる箇所を下線で表示します。スペルミスの防止に役立ちます。 28 | 29 | ## 操作Tips 30 | 31 | ### 編集するファイルを探す 32 | 33 | Pでファイル名から検索できます。 34 | 35 | ### Markdownプレビューを表示する方法 36 | 37 | VS Codeでは次のショートカットキーでMarkdownプレビューが表示できます。 38 | 39 | - Windows: CtrlKを同時押しし、すぐにVを押す。 40 | - macOS: Kを同時押しし、すぐにVを押す。 41 | -------------------------------------------------------------------------------- /docs/writing/writing.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: 執筆者向けのドキュメントです。 3 | slug: /writing 4 | --- 5 | 6 | # README 7 | 8 | [CONTRIBUTING](contributing.md) 9 | 10 | [はじめて執筆する方へ](getting-started.md) 11 | 12 | [執筆の流れ](how-to-change.md) 13 | 14 | [PDR](/writing/pdr) 15 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-utils": { 4 | "inputs": { 5 | "systems": "systems" 6 | }, 7 | "locked": { 8 | "lastModified": 1731533236, 9 | "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", 10 | "owner": "numtide", 11 | "repo": "flake-utils", 12 | "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", 13 | "type": "github" 14 | }, 15 | "original": { 16 | "owner": "numtide", 17 | "repo": "flake-utils", 18 | "type": "github" 19 | } 20 | }, 21 | "nixpkgs": { 22 | "locked": { 23 | "lastModified": 1732014248, 24 | "narHash": "sha256-y/MEyuJ5oBWrWAic/14LaIr/u5E0wRVzyYsouYY3W6w=", 25 | "owner": "NixOS", 26 | "repo": "nixpkgs", 27 | "rev": "23e89b7da85c3640bbc2173fe04f4bd114342367", 28 | "type": "github" 29 | }, 30 | "original": { 31 | "owner": "NixOS", 32 | "ref": "nixos-unstable", 33 | "repo": "nixpkgs", 34 | "type": "github" 35 | } 36 | }, 37 | "root": { 38 | "inputs": { 39 | "flake-utils": "flake-utils", 40 | "nixpkgs": "nixpkgs" 41 | } 42 | }, 43 | "systems": { 44 | "locked": { 45 | "lastModified": 1681028828, 46 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 47 | "owner": "nix-systems", 48 | "repo": "default", 49 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 50 | "type": "github" 51 | }, 52 | "original": { 53 | "owner": "nix-systems", 54 | "repo": "default", 55 | "type": "github" 56 | } 57 | } 58 | }, 59 | "root": "root", 60 | "version": 7 61 | } 62 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 4 | flake-utils.url = "github:numtide/flake-utils"; 5 | }; 6 | 7 | outputs = { self, nixpkgs, flake-utils }: 8 | flake-utils.lib.eachDefaultSystem (system: 9 | let 10 | pkgs = import nixpkgs { 11 | inherit system; 12 | overlays = [ 13 | (final: prev: { 14 | # このワークスペースで使うNode.jsのバージョンの指定 15 | nodejs = prev.nodejs_20; 16 | 17 | # NPMパッケージの実行形式が使うNode.jsのバージョンを上と同一にする設定 18 | buildNpmPackage = prev.buildNpmPackage.override { 19 | nodejs = final.nodejs; 20 | }; 21 | }) 22 | ]; 23 | }; 24 | 25 | # 開発で使用するツールの宣言 26 | tools = with pkgs; [ 27 | nodejs 28 | yarn-berry 29 | ]; 30 | in 31 | { 32 | # IDEへの対応 33 | # `nix profile install` で ~/.nix-profile/bin にインストールされるため、/workspace 外でもツールを利用できるようになります。 34 | # これは、VS CodeやJetBrains IDEなどのプロセスが、/workspace外で起動することに対応することができます。 35 | defaultPackage = pkgs.symlinkJoin { 36 | name = "workspace-tools"; 37 | paths = tools; 38 | # symlinkJoinはnodePackagesで導入される実行形式にリンクを貼れないため、その手当となる設定 39 | postBuild = '' 40 | for f in $out/lib/node_modules/.bin/*; do 41 | path="$(readlink --canonicalize-missing "$f")" 42 | ln -s "$path" "$out/bin/$(basename $f)" 43 | done 44 | ''; 45 | }; 46 | 47 | # `nix develop` への対応。 48 | devShells.default = pkgs.mkShell { 49 | buildInputs = tools; 50 | shellHook = '' 51 | if [ -n "$SHELL" ]; then 52 | exec $SHELL 53 | else 54 | echo "SHELL environment variable is not set. Using default shell." 55 | fi 56 | ''; 57 | }; 58 | 59 | formatter = pkgs.nixpkgs-fmt; 60 | } 61 | ); 62 | } 63 | -------------------------------------------------------------------------------- /gpts/README.md: -------------------------------------------------------------------------------- 1 | # gpts 2 | 3 | このディレクトリではサバイバルTypeScriptのGPTsのデータを管理しています。 4 | 5 | ## ファイル 6 | 7 | - crete-knowledge.ts: ドキュメント一覧から知識データを自動生成するスクリプト 8 | - docs.json: 自動生成した知識データ 9 | - prompt.txt: GPTsのプロンプトテキスト 10 | 11 | ## 知識データの作り方 12 | 13 | リポジトリのルートディレクトリで次のnpmスクリプトを実行してください。 14 | 環境構築を簡略化するためにnpmスクリプトはbunでの実行を想定しています。 15 | 16 | ```sh 17 | yarn create-gpts-knowledge 18 | ``` 19 | -------------------------------------------------------------------------------- /gpts/prompt.txt: -------------------------------------------------------------------------------- 1 | docs.json is a file contains information for pages of "サバイバルTypescript" which is the document for TypeScript. 2 | 3 | Please answer the question by Japanese based on docs.json and the following answer process. 4 | 5 | ## answer process 6 | 1. Search in the docs.json based on topics and keywords related to the question and provide information. 7 | 2. Add document url and title which you referenced to your answer. 8 | 3. Url and title must be contained in the docs.json 9 | 4. Don’t use markdown syntax when you write a hyper link and write the url. 10 | 5. Answer by Japanese 11 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | roots: ["/src"], 3 | testMatch: [ 4 | "**/__tests__/**/*.+(ts|tsx|js)", 5 | "**/?(*.)+(spec|test).+(ts|tsx|js)", 6 | ], 7 | transform: { 8 | "^.+\\.(ts|tsx)$": "ts-jest", 9 | }, 10 | snapshotSerializers: [ 11 | require.resolve("string-snapshot-serializer/serializer.js"), 12 | ], 13 | }; 14 | -------------------------------------------------------------------------------- /lint-staged.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "*.md": [ 3 | "markdownlint --fix", 4 | "prettier --write", 5 | "markdownlint", 6 | "textlint", 7 | ], 8 | "*.{js,jsx,ts,tsx,json,json5,css,scss,graphql,gql,html,vue,yaml}": 9 | "prettier --write", 10 | "src/**/*.{ts,tsx}": [() => "tsc"], 11 | }; 12 | -------------------------------------------------------------------------------- /prh/README.md: -------------------------------------------------------------------------------- 1 | # prh 2 | 3 | textlintで利用する表記揺れを定義した設定ファイルです。 4 | 5 | 執筆中に表記揺れを発見した場合は、`yytypescript.yml` にルールを追加していってください。 6 | -------------------------------------------------------------------------------- /prh/yytypescript.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | rules: 3 | - expected: 型アサーション 4 | patterns: タイプアサーション 5 | prh: type assertionの訳語はこれに統一します 6 | - expected: 型ガード 7 | patterns: タイプガード 8 | prh: type guardの訳語はこれに統一します 9 | - expected: オプション引数 10 | patterns: オプショナル引数 11 | prh: optional parameterの訳語はこれに統一します 12 | - expected: オプショナルチェーン 13 | patterns: 14 | - オプションチェーン 15 | - オプションチェイニング 16 | - オプショナルチェイニング 17 | prh: optional chainingの訳語はMDNに準じてこれに統一します https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Optional_chaining 18 | - expected: オプションプロパティ 19 | patterns: オプショナルプロパティ 20 | prh: optional propertyの訳語はこれに統一します 21 | - expected: インデックス型 22 | patterns: インデックスシグネチャ 23 | prh: index signatureの訳語はこれに統一します 24 | - expected: Mapped Types 25 | patterns: 26 | - マップ型 27 | - マップタイプ 28 | - マップドタイプ 29 | prh: Mapped Typesの訳語はこれに統一します。TypeScript Deep Diveでは「マップ型」と訳していますが、Mapと曖昧であることと、「マップ型」が浸透していないため訳しません。 30 | - expected: ポリフィル 31 | patterns: /[pP]olyfill/ 32 | - expected: 巻き上げ 33 | patterns: 巻上げ 34 | - expected: 再帰呼び出し 35 | patterns: 再起呼び出し 36 | - expected: null型 37 | patterns: 38 | - Null型 39 | - ヌル型 40 | - expected: undefined型 41 | patterns: 42 | - Undefined型 43 | - アンディファインド型 44 | - expected: boolean型 45 | patterns: 46 | - 論理型 47 | - 真偽値型 48 | - 真偽型 49 | - expected: number型 50 | patterns: 51 | - 数値型 52 | - expected: bigint型 53 | patterns: 54 | - Bigint型 55 | - 長整数型 56 | - expected: string型 57 | patterns: 58 | - 文字列型 59 | - expected: symbol型 60 | patterns: 61 | - シンボル型 62 | - expected: object型 63 | patterns: 64 | - オブジェクト型 -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/docusaurusPlugin.js: -------------------------------------------------------------------------------- 1 | const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin"); 2 | /** 3 | * @param context {import('@docusaurus/types').LoadContext} 4 | * @param options {{}} 5 | * @return {import('@docusaurus/types').Plugin} 6 | */ 7 | module.exports = (context, options) => ({ 8 | name: "monaco-editor", 9 | configureWebpack: (config, isServer) => { 10 | return { 11 | plugins: [new MonacoWebpackPlugin({ languages: ["typescript"] })], 12 | }; 13 | }, 14 | }); 15 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/findByPoint.test.ts: -------------------------------------------------------------------------------- 1 | import { findByPoint } from "./findByPoint"; 2 | import { print } from "./print"; 3 | 4 | test("position between two statements", () => { 5 | // language=TypeScript 6 | const code = `if(1){1}if(2){2}`; 7 | const fragments = findByPoint(code, { line: 1, column: 9 }); 8 | expect(print(fragments)).toMatchInlineSnapshot( 9 | `- IfStatement (1:9-1:17) if(2){2}` 10 | ); 11 | }); 12 | 13 | test("EndOfFileToken is removed", () => { 14 | // language=TypeScript 15 | const code = `1`; 16 | const fragments = findByPoint(code, { line: 1, column: 2 }); 17 | expect(print(fragments)).toMatchInlineSnapshot( 18 | `- ExpressionStatement,FirstLiteralToken (1:1-1:2) 1` 19 | ); 20 | }); 21 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/index.ts: -------------------------------------------------------------------------------- 1 | import { SyntaxKind } from "typescript"; 2 | import { CustomTopic } from "./topics"; 3 | 4 | export { findByPoint } from "./findByPoint"; 5 | 6 | export type Fragment = Readonly<{ 7 | code: string; 8 | position: Position; 9 | topics: ReadonlySet; 10 | }>; 11 | export type Topic = SyntaxKind | CustomTopic; 12 | export type Position = Readonly<{ start: Point; end: Point }>; 13 | export type Point = Readonly<{ line: number; column: number }>; 14 | 15 | export { getTopicDetail, getTopicDetails, type TopicDetail } from "./topics"; 16 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/nodeUtils.ts: -------------------------------------------------------------------------------- 1 | import { getPositionOfLineAndCharacter, Node, SourceFile } from "typescript"; 2 | import { Point, Position } from "./index"; 3 | 4 | export const positionOf = (node: Node): Position => { 5 | const sourceFile = node.getSourceFile(); 6 | return { 7 | start: pointOf(sourceFile, node.getStart(sourceFile, true)), 8 | end: pointOf(sourceFile, node.getEnd()), 9 | }; 10 | }; 11 | 12 | const pointOf = (sourceFile: SourceFile, pos: number): Point => { 13 | const { line, character } = sourceFile.getLineAndCharacterOfPosition(pos); 14 | return { line: line + 1, column: character + 1 }; 15 | }; 16 | 17 | export const posOf = (sourceFile: SourceFile, point: Point): number => { 18 | try { 19 | return getPositionOfLineAndCharacter( 20 | sourceFile, 21 | point.line - 1, 22 | point.column - 1 23 | ); 24 | } catch (e: any) { 25 | console.error(Object.assign(e, { point })); 26 | return NaN; 27 | } 28 | }; 29 | 30 | export const childrenOf = (node: Node): ReadonlySet => { 31 | const children = new Set(); 32 | node.forEachChild((child) => { 33 | children.add(child); 34 | }); 35 | return children; 36 | }; 37 | 38 | export const isWithIn = (node: Node, pos: number): boolean => 39 | node.getStart() <= pos && pos <= node.getEnd(); 40 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/print.ts: -------------------------------------------------------------------------------- 1 | import { SyntaxKind } from "typescript"; 2 | import { Fragment, Position, Topic } from "./index"; 3 | 4 | export const print = (fragments: ReadonlyArray): string => 5 | fragments.map(stringOfFragment).join("\n"); 6 | 7 | const stringOfFragment = ({ topics, position, code }: Fragment): string => 8 | `- ${stringOfTopics(topics)} (${stringOfPosition(position)}) ${stringOfCode( 9 | code 10 | )}`; 11 | 12 | const stringOfTopics = (topics: ReadonlySet): string => 13 | Array.from(topics).map(stringOfTopic).join(","); 14 | 15 | const stringOfTopic = (topic: Topic): string => 16 | typeof topic === "string" ? topic : SyntaxKind[topic]!; 17 | 18 | const stringOfCode = (code: string): string => { 19 | const lines = code.split("\n"); 20 | const extra = lines.length > 1 ? ` [${lines.length}]` : ""; 21 | return `${lines[0]}${extra}`; 22 | }; 23 | 24 | const stringOfPosition = ({ start, end }: Position): string => 25 | `${start.line}:${start.column}-${end.line}:${end.column}`; 26 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/asExpression.ts: -------------------------------------------------------------------------------- 1 | import { isAsExpression, isTypeReferenceNode } from "typescript"; 2 | import { CustomTopic, Transform } from "./utils"; 3 | 4 | export const asExpression: Transform = ({ node, result }) => { 5 | if (!isAsExpression(node)) { 6 | return; 7 | } 8 | if (isTypeReferenceNode(node.type) && node.type.getText() === "const") { 9 | result.addFragmentWithTopic(node, CustomTopic.ConstAssertion); 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/asKeyword.ts: -------------------------------------------------------------------------------- 1 | import { isMappedTypeNode, SyntaxKind } from "typescript"; 2 | import { nextOf, positionOf, Transform } from "./utils"; 3 | 4 | export const asKeyword: Transform = ({ node, result }) => { 5 | if (node.kind !== SyntaxKind.AsKeyword) { 6 | return; 7 | } 8 | 9 | if (isMappedTypeNode(node.parent)) { 10 | const next = nextOf(node); 11 | if (next) { 12 | result.addFragment({ 13 | code: `as ${next.getText()}`, 14 | position: { start: positionOf(node).start, end: positionOf(next).end }, 15 | topics: new Set(["KeyRemappingViaAs"]), 16 | }); 17 | return; 18 | } 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/asteriskToken.ts: -------------------------------------------------------------------------------- 1 | import { 2 | isAsteriskToken, 3 | isFunctionDeclaration, 4 | isFunctionExpression, 5 | isMethodDeclaration, 6 | isYieldExpression, 7 | isBinaryExpression, 8 | } from "typescript"; 9 | import { childrenOf, CustomTopic, Transform } from "./utils"; 10 | 11 | export const asteriskToken: Transform = ({ node, result }) => { 12 | if (!isAsteriskToken(node)) { 13 | return; 14 | } 15 | 16 | const parent = node.parent; 17 | if (isBinaryExpression(parent)) { 18 | result.addFragmentWithTopic(node, CustomTopic.MultiplicationOperator); 19 | } else if ( 20 | isFunctionDeclaration(parent) || 21 | isFunctionExpression(parent) || 22 | isMethodDeclaration(parent) 23 | ) { 24 | result.addFragmentWithTopic(node, CustomTopic.Generator); 25 | } else if (isYieldExpression(parent)) { 26 | result.addFragmentWithTopic(node, CustomTopic.YieldAsterisk); 27 | } else { 28 | result.addFragment(node); 29 | } 30 | 31 | result.addChildren(childrenOf(node)); 32 | }; 33 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/defaultTransform.ts: -------------------------------------------------------------------------------- 1 | import { childrenOf, Transform } from "./utils"; 2 | 3 | export const defaultTransform: Transform = ({ node, result }) => 4 | result.addFragment(node).addChildren(childrenOf(node)); 5 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/equalsGreaterThanToken.test.ts: -------------------------------------------------------------------------------- 1 | import { findByPoint } from "../findByPoint"; 2 | import { print } from "../print"; 3 | 4 | describe("EqualsGreaterThanToken", () => { 5 | test("EqualsGreaterThanToken is removed in arrow function", () => { 6 | // language=TypeScript 7 | const code = `() => {};`; 8 | const fragments = findByPoint(code, { line: 1, column: 4 }); 9 | expect(print(fragments)).toMatchInlineSnapshot(` 10 | - ExpressionStatement (1:1-1:10) () => {}; 11 | - ArrowFunction (1:1-1:9) () => {} 12 | `); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/equalsGreaterThanToken.ts: -------------------------------------------------------------------------------- 1 | import { isArrowFunction, SyntaxKind } from "typescript"; 2 | import { childrenOf, Transform } from "./utils"; 3 | 4 | export const equalsGreaterThanToken: Transform = ({ node, result }) => { 5 | if (node.kind !== SyntaxKind.EqualsGreaterThanToken) { 6 | return; 7 | } 8 | 9 | // if parent is arrow function, this token is ignored. 10 | if (!isArrowFunction(node.parent)) { 11 | result.addFragment(node); 12 | } 13 | 14 | result.addChildren(childrenOf(node)); 15 | }; 16 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/exclamationToken.test.ts: -------------------------------------------------------------------------------- 1 | import { findByPoint } from "../findByPoint"; 2 | import { print } from "../print"; 3 | import { CustomTopic } from "./utils"; 4 | 5 | describe("LogicalNotOperator", () => { 6 | test("not 0", () => { 7 | // language=TypeScript 8 | const code = `!0;`; 9 | const fragments = findByPoint(code, { line: 1, column: 1 }); 10 | expect(print(fragments)).toMatchInlineSnapshot(` 11 | - ExpressionStatement (1:1-1:4) !0; 12 | - PrefixUnaryExpression (1:1-1:3) !0 13 | `); 14 | }); 15 | }); 16 | 17 | describe(CustomTopic.DefiniteAssignmentAssertion, () => { 18 | test("variable declaration", () => { 19 | // language=TypeScript 20 | const code = `let num!: number;`; 21 | const fragments = findByPoint(code, { line: 1, column: 8 }); 22 | expect(print(fragments)).toMatchInlineSnapshot(` 23 | - FirstStatement (1:1-1:18) let num!: number; 24 | - VariableDeclarationList (1:1-1:17) let num!: number 25 | - VariableDeclaration (1:5-1:17) num!: number 26 | - TypeAnnotationOfVariable (1:11-1:17) number 27 | - DefiniteAssignmentAssertion (1:8-1:9) ! 28 | `); 29 | }); 30 | 31 | test("class property", () => { 32 | // language=TypeScript 33 | const code = `class X { 34 | prop!: string; 35 | }`; 36 | const fragments = findByPoint(code, { line: 2, column: 7 }); 37 | expect(print(fragments)).toMatchInlineSnapshot(` 38 | - ClassDeclaration (1:1-3:2) class X { [3] 39 | - PropertyDeclaration (2:3-2:17) prop!: string; 40 | - DefiniteAssignmentAssertion (2:7-2:8) ! 41 | `); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/exclamationToken.ts: -------------------------------------------------------------------------------- 1 | import { SyntaxKind } from "typescript"; 2 | import { childrenOf, CustomTopic, Transform } from "./utils"; 3 | 4 | export const exclamationToken: Transform = ({ node, result }) => { 5 | if (node.kind !== SyntaxKind.ExclamationToken) { 6 | return; 7 | } 8 | result.addFragmentWithTopic(node, CustomTopic.DefiniteAssignmentAssertion); 9 | result.addChildren(childrenOf(node)); 10 | }; 11 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/heritageClause.ts: -------------------------------------------------------------------------------- 1 | import { isHeritageClause, SyntaxKind } from "typescript"; 2 | import { childrenOf, CustomTopic, Transform } from "./utils"; 3 | 4 | export const heritageClause: Transform = ({ node, result }) => { 5 | if (!isHeritageClause(node)) { 6 | return; 7 | } 8 | 9 | const firstChild = node.getChildAt(0); 10 | if (firstChild.kind === SyntaxKind.ExtendsKeyword) { 11 | result.addFragmentWithTopic(node, CustomTopic.ExtendsClass); 12 | } else if (firstChild.kind === SyntaxKind.ImplementsKeyword) { 13 | result.addFragmentWithTopic(node, CustomTopic.ImplementsInterface); 14 | } else { 15 | result.addFragment(node); 16 | } 17 | result.addChildren(childrenOf(node)); 18 | }; 19 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/index.ts: -------------------------------------------------------------------------------- 1 | import { Node } from "typescript"; 2 | import { Fragment, Topic } from "../index"; 3 | import { asExpression } from "./asExpression"; 4 | import { asKeyword } from "./asKeyword"; 5 | import { asteriskToken } from "./asteriskToken"; 6 | import { defaultTransform } from "./defaultTransform"; 7 | import { equalsGreaterThanToken } from "./equalsGreaterThanToken"; 8 | import { exclamationToken } from "./exclamationToken"; 9 | import { heritageClause } from "./heritageClause"; 10 | import { mappedType } from "./mappedType"; 11 | import { minusToken } from "./minusToken"; 12 | import { nullKeyword } from "./nullKeyword"; 13 | import { parameter } from "./parameter"; 14 | import { plusToken } from "./plusToken"; 15 | import { questionToken } from "./questionToken"; 16 | import { typeOperator } from "./typeOperator"; 17 | import { variableDeclaration } from "./variableDeclaration"; 18 | import { variableDeclarationList } from "./variableDeclarationList"; 19 | 20 | export type Transform = ({ node, result }: TransformParams) => void; 21 | export type TransformParams = Readonly<{ 22 | node: Node; 23 | pos: number; 24 | result: Result; 25 | }>; 26 | export type Result = { 27 | addFragment: (fragment: Fragment | Node) => Result; 28 | addFragmentWithTopic: (node: Node, topic: Topic) => Result; 29 | addChild: (child: Node) => Result; 30 | addChildren: (children: ReadonlySet) => Result; 31 | }; 32 | export const transforms: ReadonlyArray = [ 33 | questionToken, 34 | nullKeyword, 35 | equalsGreaterThanToken, 36 | plusToken, 37 | minusToken, 38 | asteriskToken, 39 | exclamationToken, 40 | typeOperator, 41 | asKeyword, 42 | asExpression, 43 | heritageClause, 44 | variableDeclarationList, 45 | variableDeclaration, 46 | parameter, 47 | mappedType, 48 | defaultTransform, 49 | ]; 50 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/minusToken.test.ts: -------------------------------------------------------------------------------- 1 | import { findByPoint } from "../findByPoint"; 2 | import { print } from "../print"; 3 | 4 | describe("MinusToken", () => { 5 | test("subtraction", () => { 6 | // language=TypeScript 7 | const code = `1 - 1;`; 8 | const fragments = findByPoint(code, { line: 1, column: 3 }); 9 | expect(print(fragments)).toMatchInlineSnapshot(` 10 | - ExpressionStatement (1:1-1:7) 1 - 1; 11 | - BinaryExpression (1:1-1:6) 1 - 1 12 | - MinusToken (1:3-1:4) - 13 | `); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/minusToken.ts: -------------------------------------------------------------------------------- 1 | import { isMappedTypeNode, isMinusToken, SyntaxKind } from "typescript"; 2 | import { childrenOf, CustomTopic, nextOf, Transform } from "./utils"; 3 | 4 | export const minusToken: Transform = ({ node, result }) => { 5 | if (!isMinusToken(node)) { 6 | return; 7 | } 8 | 9 | if (isMappedTypeNode(node.parent)) { 10 | const next = nextOf(node); 11 | if (next) { 12 | if (next.kind === SyntaxKind.ReadonlyKeyword) { 13 | result.addFragmentWithTopic( 14 | node, 15 | CustomTopic.MinusReadonlyOfMappedType 16 | ); 17 | return; 18 | } 19 | if (next.kind === SyntaxKind.QuestionToken) { 20 | result.addFragmentWithTopic( 21 | node, 22 | CustomTopic.MinusOptionTypeOfMappedType 23 | ); 24 | return; 25 | } 26 | } 27 | } 28 | 29 | result.addFragment(node); 30 | result.addChildren(childrenOf(node)); 31 | }; 32 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/nullKeyword.test.ts: -------------------------------------------------------------------------------- 1 | import { findByPoint } from "../findByPoint"; 2 | import { print } from "../print"; 3 | import { CustomTopic } from "./utils"; 4 | 5 | describe(CustomTopic.NullType, () => { 6 | test("type annotation of variable", () => { 7 | // language=TypeScript 8 | const code = `let a: null;`; 9 | const fragments = findByPoint(code, { line: 1, column: 8 }); 10 | expect(print(fragments)).toMatchInlineSnapshot(` 11 | - FirstStatement (1:1-1:13) let a: null; 12 | - VariableDeclarationList (1:1-1:12) let a: null 13 | - VariableDeclaration (1:5-1:12) a: null 14 | - TypeAnnotationOfVariable,LiteralType,NullType (1:8-1:12) null 15 | `); 16 | }); 17 | }); 18 | 19 | describe(CustomTopic.NullLiteral, () => { 20 | test("in a variable declaration", () => { 21 | // language=TypeScript 22 | const code = `let a = null`; 23 | const fragments = findByPoint(code, { line: 1, column: 9 }); 24 | expect(print(fragments)).toMatchInlineSnapshot(` 25 | - FirstStatement,VariableDeclarationList (1:1-1:13) let a = null 26 | - VariableDeclaration (1:5-1:13) a = null 27 | - NullLiteral (1:9-1:13) null 28 | `); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/nullKeyword.ts: -------------------------------------------------------------------------------- 1 | import { isLiteralTypeNode, SyntaxKind } from "typescript"; 2 | import { childrenOf, CustomTopic, Transform } from "./utils"; 3 | 4 | export const nullKeyword: Transform = ({ node, result }) => { 5 | if (node.kind !== SyntaxKind.NullKeyword) { 6 | return; 7 | } 8 | 9 | if (isLiteralTypeNode(node.parent)) { 10 | result.addFragmentWithTopic(node, CustomTopic.NullType); 11 | } else { 12 | result.addFragmentWithTopic(node, CustomTopic.NullLiteral); 13 | } 14 | result.addChildren(childrenOf(node)); 15 | }; 16 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/parameter.ts: -------------------------------------------------------------------------------- 1 | import { 2 | isArrowFunction, 3 | isConstructorDeclaration, 4 | isFunctionDeclaration, 5 | isFunctionExpression, 6 | isMethodDeclaration, 7 | isParameter, 8 | isSetAccessor, 9 | Node, 10 | ParameterDeclaration, 11 | } from "typescript"; 12 | 13 | import { childrenOf, CustomTopic, Result, Transform } from "./utils"; 14 | 15 | export const parameter: Transform = ({ node, result }) => { 16 | if (!isParameter(node)) { 17 | return; 18 | } 19 | const topic = topicOf(node.parent); 20 | if (topic) { 21 | if (topic === CustomTopic.ParameterOfConstructor) { 22 | parameterOfConstructor(node, result); 23 | } else { 24 | result.addFragmentWithTopic(node, topic); 25 | } 26 | } else { 27 | result.addFragment(node); 28 | } 29 | result.addChildren(childrenOf(node)); 30 | }; 31 | 32 | const topicOf = (node: Node): CustomTopic | undefined => { 33 | return isFunctionDeclaration(node) || 34 | isArrowFunction(node) || 35 | isFunctionExpression(node) 36 | ? CustomTopic.ParameterOfFunction 37 | : isMethodDeclaration(node) || isSetAccessor(node) 38 | ? CustomTopic.ParameterOfMethod 39 | : isConstructorDeclaration(node) 40 | ? CustomTopic.ParameterOfConstructor 41 | : undefined; 42 | }; 43 | 44 | const parameterOfConstructor = (node: ParameterDeclaration, result: Result) => { 45 | if (node.modifiers?.length ?? 0 > 1) { 46 | result.addFragmentWithTopic(node, CustomTopic.ConstructorShorthand); 47 | } 48 | result.addFragmentWithTopic(node, CustomTopic.ParameterOfConstructor); 49 | }; 50 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/plusToken.test.ts: -------------------------------------------------------------------------------- 1 | import { findByPoint } from "../findByPoint"; 2 | import { print } from "../print"; 3 | 4 | describe("PlusToken", () => { 5 | test("Addition", () => { 6 | // language=TypeScript 7 | const code = `1 + 1;`; 8 | const fragments = findByPoint(code, { line: 1, column: 3 }); 9 | expect(print(fragments)).toMatchInlineSnapshot(` 10 | - ExpressionStatement (1:1-1:7) 1 + 1; 11 | - BinaryExpression (1:1-1:6) 1 + 1 12 | - PlusToken (1:3-1:4) + 13 | `); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/plusToken.ts: -------------------------------------------------------------------------------- 1 | import { isMappedTypeNode, isPlusToken, SyntaxKind } from "typescript"; 2 | import { childrenOf, CustomTopic, nextOf, Transform } from "./utils"; 3 | 4 | export const plusToken: Transform = ({ node, result }) => { 5 | if (!isPlusToken(node)) { 6 | return; 7 | } 8 | 9 | if (isMappedTypeNode(node.parent)) { 10 | const next = nextOf(node); 11 | if (next) { 12 | if (next.kind === SyntaxKind.ReadonlyKeyword) { 13 | result.addFragmentWithTopic(node, CustomTopic.PlusReadonlyOfMappedType); 14 | return; 15 | } 16 | if (next.kind === SyntaxKind.QuestionToken) { 17 | result.addFragmentWithTopic( 18 | node, 19 | CustomTopic.PlusOptionTypeOfMappedType 20 | ); 21 | return; 22 | } 23 | } 24 | } 25 | 26 | result.addFragment(node); 27 | result.addChildren(childrenOf(node)); 28 | }; 29 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/questionToken.test.ts: -------------------------------------------------------------------------------- 1 | import { findByPoint } from "../findByPoint"; 2 | import { print } from "../print"; 3 | 4 | describe("QuestionToken", () => { 5 | test("conditional expression", () => { 6 | // language=TypeScript 7 | const code = `0 ? 0 : 0;`; 8 | const fragments = findByPoint(code, { line: 1, column: 3 }); 9 | expect(print(fragments)).toMatchInlineSnapshot(` 10 | - ExpressionStatement (1:1-1:11) 0 ? 0 : 0; 11 | - ConditionalExpression (1:1-1:10) 0 ? 0 : 0 12 | `); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/questionToken.ts: -------------------------------------------------------------------------------- 1 | import { 2 | isConditionalExpression, 3 | isMappedTypeNode, 4 | Node, 5 | QuestionToken, 6 | SyntaxKind, 7 | } from "typescript"; 8 | import { childrenOf, CustomTopic, Transform } from "./utils"; 9 | 10 | export const questionToken: Transform = ({ node, result }) => { 11 | if (!isQuestionToken(node)) { 12 | return; 13 | } 14 | 15 | // fragment is not added if parent is conditional expression 16 | if (isConditionalExpression(node.parent)) { 17 | result.addChildren(childrenOf(node)); 18 | return; 19 | } 20 | 21 | if (isMappedTypeNode(node.parent)) { 22 | result.addFragmentWithTopic(node, CustomTopic.OptionProperty); 23 | return; 24 | } 25 | 26 | result.addFragment(node); 27 | }; 28 | 29 | const isQuestionToken = (node: Node): node is QuestionToken => { 30 | return node.kind === SyntaxKind.QuestionToken; 31 | }; 32 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/typeOperator.ts: -------------------------------------------------------------------------------- 1 | import { 2 | isArrayTypeNode, 3 | isTypeOperatorNode, 4 | SyntaxKind, 5 | TypeOperatorNode, 6 | } from "typescript"; 7 | import { childrenOf, CustomTopic, Transform, Result } from "./utils"; 8 | 9 | export const typeOperator: Transform = ({ node, result }) => { 10 | if (!isTypeOperatorNode(node)) { 11 | return; 12 | } 13 | 14 | switch (node.operator) { 15 | case SyntaxKind.ReadonlyKeyword: 16 | return readonly(node, result); 17 | case SyntaxKind.UniqueKeyword: 18 | return uniqueSymbol(node, result); 19 | case SyntaxKind.KeyOfKeyword: 20 | return keyofKeyword(node, result); 21 | } 22 | }; 23 | 24 | const readonly = (node: TypeOperatorNode, result: Result): void => { 25 | const child = node.getChildAt(1); 26 | if (!isArrayTypeNode(child)) { 27 | return; 28 | } 29 | result 30 | .addFragmentWithTopic(node, CustomTopic.ReadonlyArray) 31 | .addChildren(childrenOf(child)); 32 | }; 33 | 34 | const uniqueSymbol = (node: TypeOperatorNode, result: Result): void => { 35 | const [unique, symbol] = node.getChildren(); 36 | if ( 37 | unique?.kind === SyntaxKind.UniqueKeyword && 38 | symbol?.kind === SyntaxKind.SymbolKeyword 39 | ) { 40 | result.addFragmentWithTopic(node, CustomTopic.UniqueSymbol); 41 | } 42 | }; 43 | 44 | const keyofKeyword = (node: TypeOperatorNode, result: Result): void => { 45 | const [keyofKeyword, ...children] = node.getChildren(); 46 | if (keyofKeyword) 47 | result 48 | .addFragmentWithTopic(node, SyntaxKind.KeyOfKeyword) 49 | .addChildren(new Set(children)); 50 | }; 51 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/utils.ts: -------------------------------------------------------------------------------- 1 | import { Node } from "typescript"; 2 | 3 | export { childrenOf, positionOf } from "../nodeUtils"; 4 | export { CustomTopic } from "../topics"; 5 | export type { Transform, TransformParams, Result } from "./index"; 6 | 7 | export const nextOf = (node: Node): Node | undefined => { 8 | const nodes = node.parent.getChildren(); 9 | for (const [index, current] of nodes.entries()) { 10 | if (current === node) { 11 | return nodes[index + 1]; 12 | } 13 | } 14 | return undefined; 15 | }; 16 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/variableDeclaration.ts: -------------------------------------------------------------------------------- 1 | import { 2 | isVariableDeclaration, 3 | SyntaxKind, 4 | VariableDeclaration, 5 | } from "typescript"; 6 | 7 | import { childrenOf, CustomTopic, Result, Transform } from "./utils"; 8 | 9 | export const variableDeclaration: Transform = ({ node, result }) => { 10 | if (!isVariableDeclaration(node)) { 11 | return; 12 | } 13 | result.addFragment(node).addChildren(childrenOf(node)); 14 | typeAnnotationOfVariable(node, result); 15 | }; 16 | 17 | const typeAnnotationOfVariable = ( 18 | node: VariableDeclaration, 19 | result: Result 20 | ) => { 21 | const children = node.getChildren(); 22 | children.forEach((child, index) => { 23 | const next = children[index + 1]; 24 | if (child.kind === SyntaxKind.ColonToken && next) { 25 | result.addFragmentWithTopic(next, CustomTopic.TypeAnnotationOfVariable); 26 | } 27 | }); 28 | }; 29 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/variableDeclarationList.test.ts: -------------------------------------------------------------------------------- 1 | import { findByPoint } from "../findByPoint"; 2 | import { print } from "../print"; 3 | 4 | test("VarKeyword", () => { 5 | // language=TypeScript 6 | const code = `var a: number = 1`; 7 | const fragments = findByPoint(code, { line: 1, column: 1 }); 8 | expect(print(fragments)).toMatchInlineSnapshot(` 9 | - FirstStatement,VariableDeclarationList (1:1-1:18) var a: number = 1 10 | - VarKeyword (1:1-1:4) var 11 | `); 12 | }); 13 | 14 | describe("VariableDeclarationList", () => { 15 | // language=TypeScript 16 | const code = `let var1, var2`; 17 | test("before let", () => { 18 | const fragments = findByPoint(code, { line: 1, column: 1 }); 19 | expect(print(fragments)).toMatchInlineSnapshot(` 20 | - FirstStatement,VariableDeclarationList (1:1-1:15) let var1, var2 21 | - LetKeyword (1:1-1:4) let 22 | `); 23 | }); 24 | test("before var1", () => { 25 | const fragments = findByPoint(code, { line: 1, column: 5 }); 26 | expect(print(fragments)).toMatchInlineSnapshot(` 27 | - FirstStatement,VariableDeclarationList (1:1-1:15) let var1, var2 28 | - VariableDeclaration,Identifier (1:5-1:9) var1 29 | `); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/model/transforms/variableDeclarationList.ts: -------------------------------------------------------------------------------- 1 | import { isVariableDeclarationList } from "typescript"; 2 | import { childrenOf, Transform } from "./utils"; 3 | 4 | export const variableDeclarationList: Transform = ({ node, result }) => { 5 | if (!isVariableDeclarationList(node)) { 6 | return; 7 | } 8 | // expose keywords(var, let, const) as fragments 9 | result.addFragment(node); 10 | result.addChild(node.getChildAt(0)); 11 | result.addChildren(childrenOf(node)); 12 | }; 13 | -------------------------------------------------------------------------------- /src/components/codeReadingAssistant/sampleCodes/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "jsx": "react-jsx", 5 | "experimentalDecorators": true, 6 | "module": "commonjs", 7 | "noEmit": true, 8 | "esModuleInterop": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "strict": true, 11 | "skipLibCheck": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/components/icons/Bot.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Name: ucide-icons/lucide 3 | * Version: 0.265.0 4 | * License: ISC 5 | * Repository: https://github.com/lucide-icons/lucide/ 6 | * License Copyright: 7 | * ===== 8 | * ISC License 9 | * Copyright (c) for portions of Lucide are held by Cole Bemis 2013-2022 as part of Feather (MIT). All other copyright (c) for Lucide are held by Lucide Contributors 2022. 10 | * 11 | * Permission to use, copy, modify, and/or distribute this software for any 12 | * purpose with or without fee is hereby granted, provided that the above 13 | * copyright notice and this permission notice appear in all copies. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 16 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 21 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 | */ 23 | 24 | import React from "react"; 25 | 26 | /** 27 | * Lucide bot icon 28 | * @see: https://lucide.dev/icons/bot 29 | */ 30 | export const Bot = () => ( 31 | 51 | ); 52 | -------------------------------------------------------------------------------- /src/components/ogpImage.ts: -------------------------------------------------------------------------------- 1 | import { useDoc } from "./useDoc"; 2 | 3 | export function useOgpImageUrl(): string { 4 | const { metadata, frontMatter, assets } = useDoc(); 5 | return assets.image ?? frontMatter.image ?? getOgpImageUrl(metadata.title); 6 | } 7 | 8 | export const getOgpImageUrl = (title: string): string => 9 | `https://tsbook-og-image.vercel.app/${encodeURIComponent( 10 | title 11 | )}.png?pattern=cross&md=0&fontSize=75px&textColor=%23ffffff&textStrongColor=%238340BB&overlay=https%3A%2F%2Fraw.githubusercontent.com%2Fyytypescript%2Fog-image%2Fmain%2Fpublic%2Fogp-overlay.svg`; 12 | -------------------------------------------------------------------------------- /src/components/pageRef/pageRef.tsx: -------------------------------------------------------------------------------- 1 | import DocCard from "@theme/DocCard"; 2 | import React, { FC } from "react"; 3 | 4 | export type Props = { 5 | readonly link: string; 6 | readonly title: string; 7 | }; 8 | 9 | const PageRef: FC = ({ link, title }) => { 10 | try { 11 | const { metadata } = require("@site/docs" + link.replace(/^\/+/, "/")); 12 | return ( 13 | 21 | ); 22 | } catch (e) { 23 | console.error(e); 24 | return ( 25 |

26 | {title} 27 |

28 | ); 29 | } 30 | }; 31 | export default PageRef; 32 | -------------------------------------------------------------------------------- /src/components/pageRef/pageRefRemark.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | /** 4 | * @typedef {import("mdast").Root} Root 5 | */ 6 | 7 | const fs = require("fs"); 8 | 9 | /** 10 | * @type {(settings: [never]) => (node: Root) => void} 11 | */ 12 | const pageRef = () => (node) => { 13 | let linkFound = false; 14 | 15 | for (const [index, paragraph] of node.children.entries()) { 16 | if (paragraph.type !== "paragraph") { 17 | continue; 18 | } 19 | if (paragraph.children.length !== 1) { 20 | continue; 21 | } 22 | if (paragraph.children[0]?.type !== "link") { 23 | continue; 24 | } 25 | const link = paragraph.children[0]; 26 | if (!link.url.startsWith("/")) { 27 | continue; 28 | } 29 | linkFound = true; 30 | node.children[index] = { 31 | type: /** @type {any} */ ("jsx"), 32 | value: ``, 35 | }; 36 | } 37 | 38 | if (linkFound) { 39 | node.children.unshift({ 40 | type: /** @type {any} */ ("import"), 41 | value: 'import PageRef from "@site/src/components/pageRef/pageRef";', 42 | }); 43 | } 44 | }; 45 | 46 | /** 47 | * @param {string} slug 48 | * @return {string} 49 | */ 50 | function slugToFilename(slug) { 51 | if (fs.existsSync(`./docs${slug}/README.md`)) { 52 | return `${slug}/README.md`; 53 | } 54 | return `${slug}.md`; 55 | } 56 | 57 | exports.pageRef = pageRef; 58 | -------------------------------------------------------------------------------- /src/components/postILearned/postILearned.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import nl2br from "react-nl2br"; 3 | 4 | export default function PostILearned({ 5 | children, 6 | }: { 7 | readonly children: Child | Child[]; 8 | }) { 9 | const texts = extractText(children) + "\n\n『サバイバルTypeScript』より"; 10 | return ( 11 |
12 |
13 |
学びをシェアする
14 |
15 | 26 |
27 | ); 28 | } 29 | 30 | function extractText(children: Child | Child[]): string { 31 | if (Array.isArray(children)) { 32 | return children 33 | .map((child) => extractTextFromChild(child.props)) 34 | .join("\n\n"); 35 | } else { 36 | return extractTextFromChild(children.props); 37 | } 38 | } 39 | 40 | function extractTextFromChild(props: Child["props"]): string { 41 | if (isParagraph(props)) { 42 | const { children } = props; 43 | if (typeof children === "string") { 44 | return children; 45 | } 46 | return children.filter((x): x is string => typeof x === "string").join(""); 47 | } else { 48 | return props.map((x) => extractTextFromChild(x)).join("\n\n"); 49 | } 50 | } 51 | 52 | type Child = { 53 | readonly props: Paragraph | ReadonlyArray; 54 | }; 55 | 56 | type Paragraph = { 57 | readonly mdxType: "p"; 58 | readonly children: string | ReadonlyArray; 59 | }; 60 | 61 | function isParagraph(value: Child["props"]): value is Paragraph { 62 | return ( 63 | typeof value === "object" && (value as Partial).mdxType === "p" 64 | ); 65 | } 66 | -------------------------------------------------------------------------------- /src/components/postILearned/postILearnedRemark.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | /** 4 | * @typedef {import("mdast").Root} Root 5 | */ 6 | 7 | /** 8 | * @type {(settings: [never]) => (node: Root) => void} 9 | */ 10 | exports.postILearned = () => (node) => { 11 | node.children.unshift({ 12 | type: /** @type {any} */ ("import"), 13 | value: 14 | 'import PostILearned from "@site/src/components/postILearned/postILearned";', 15 | }); 16 | }; 17 | -------------------------------------------------------------------------------- /src/components/questionAndReportIssue.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from "react"; 2 | import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; 3 | 4 | export type Props = { 5 | readonly editUrl: string; 6 | }; 7 | 8 | export const QuestionAndReportIssue: FC = ({ editUrl }) => { 9 | const { siteConfig } = useDocusaurusContext(); 10 | const { organizationName, projectName } = siteConfig; 11 | const baseUrl = `https://github.com/${organizationName}/${projectName}`; 12 | return ( 13 | 40 | ); 41 | }; 42 | -------------------------------------------------------------------------------- /src/components/useDoc.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | import { useDoc as useDocOrig } from "@docusaurus/theme-common/internal"; 3 | import { DocContextValue } from "@docusaurus/theme-common/lib/contexts/doc"; 4 | 5 | // For future compatibility with Docusaurus, this hook encapsulates the useColorMode hook. Docusaurus sometimes makes breaking changes... 6 | export const useDoc: () => DocContextValue = useDocOrig; 7 | -------------------------------------------------------------------------------- /src/components/useIsDarkMode.ts: -------------------------------------------------------------------------------- 1 | import { useColorMode as useColorMode } from "@docusaurus/theme-common"; 2 | 3 | // For future compatibility with Docusaurus, this hook encapsulates the useColorMode hook. Docusaurus sometimes makes breaking changes... 4 | export const useIsDarkMode = () => useColorMode().colorMode === "dark"; 5 | -------------------------------------------------------------------------------- /src/pages/code-reading-assistant.module.css: -------------------------------------------------------------------------------- 1 | .readme { 2 | --font-size: 0.85rem; 3 | --ifm-h1-font-size: calc(var(--font-size) * 2); 4 | --ifm-h2-font-size: calc(var(--font-size) * 1.5); 5 | --ifm-h3-font-size: calc(var(--font-size) * 1.25); 6 | --ifm-h4-font-size: var(--font-size); 7 | --ifm-h5-font-size: calc(var(--font-size) * 0.875); 8 | --ifm-h6-font-size: calc(var(--font-size) * 0.85); 9 | font-size: var(--font-size); 10 | } 11 | -------------------------------------------------------------------------------- /src/pages/code-reading-assistant.tsx: -------------------------------------------------------------------------------- 1 | import BrowserOnly from "@docusaurus/BrowserOnly"; 2 | import { getOgpImageUrl } from "../components/ogpImage"; 3 | import Layout from "@theme/Layout"; 4 | import React from "react"; 5 | import styles from "./code-reading-assistant.module.css"; 6 | // @ts-expect-error 7 | import ReadMe from "../components/codeReadingAssistant/README.md"; 8 | import Head from "@docusaurus/Head"; 9 | 10 | const App = React.lazy( 11 | () => 12 | import( 13 | /* webpackChunkName: "codeReadingAssistant" */ "../components/codeReadingAssistant" 14 | ) 15 | ); 16 | 17 | const CodeReadingAssistant: React.FC = () => { 18 | const readme = ( 19 |
20 | 21 |
22 | ); 23 | const pageImage = getOgpImageUrl("TypeScript解読アシスタント"); 24 | return ( 25 | 30 | 31 | 32 | 33 | 34 | 35 | {() => ( 36 | 37 | 38 | 39 | )} 40 | 41 | 42 | ); 43 | }; 44 | 45 | export default CodeReadingAssistant; 46 | 47 | const Loading =
読込中...
; 48 | -------------------------------------------------------------------------------- /src/theme/DocItem/Metadata/index.tsx: -------------------------------------------------------------------------------- 1 | import { PageMetadata } from "@docusaurus/theme-common"; 2 | import React from "react"; 3 | import { useOgpImageUrl } from "../../../components/ogpImage"; 4 | import { useDoc } from "../../../components/useDoc"; 5 | 6 | export default function MetadataWrapper() { 7 | const { metadata, frontMatter } = useDoc(); 8 | const ogpImageUrl = useOgpImageUrl(); 9 | return ( 10 | <> 11 | 17 | 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /src/theme/EditThisPage/index.tsx: -------------------------------------------------------------------------------- 1 | import { Props } from "@theme/EditThisPage"; 2 | import React from "react"; 3 | import { QuestionAndReportIssue } from "../../components/questionAndReportIssue"; 4 | 5 | export default function EditThisPageWrapper({ editUrl }: Props) { 6 | return ; 7 | } 8 | -------------------------------------------------------------------------------- /src/theme/NavbarItem/HtmlNavbarItem/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import HtmlNavbarItem from "@theme-original/NavbarItem/HtmlNavbarItem"; 3 | import { Props } from "@theme/NavbarItem/HtmlNavbarItem"; 4 | import { Bot } from "../../../components/icons/Bot"; 5 | 6 | export default function HtmlNavbarItemWrapper(props: Props) { 7 | // モバイルの場合はメニューのリスト項目として表示するためにラップする要素を変更 8 | const Item = ({ children }: { children: React.ReactNode }) => 9 | props.mobile ? ( 10 |
  • {children}
  • 11 | ) : ( 12 |
    {children}
    13 | ); 14 | 15 | if (props.value === "custom-ask-to-ai-link") { 16 | return ( 17 | 18 | 33 | 34 | AIに質問する 35 | 48 | 49 | 50 | ); 51 | } 52 | 53 | return ; 54 | } 55 | -------------------------------------------------------------------------------- /static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/.nojekyll -------------------------------------------------------------------------------- /static/img/browser-rendering-engine-javascript-engine-ecmascript-relations.eps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/browser-rendering-engine-javascript-engine-ecmascript-relations.eps -------------------------------------------------------------------------------- /static/img/difference-among-object-and-object.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/difference-among-object-and-object.png -------------------------------------------------------------------------------- /static/img/how-to-loop-an-array.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/how-to-loop-an-array.png -------------------------------------------------------------------------------- /static/img/js.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/img/ogp.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/ogp.ai -------------------------------------------------------------------------------- /static/img/ogp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/ogp.png -------------------------------------------------------------------------------- /static/img/range-of-typescript.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/range-of-typescript.png -------------------------------------------------------------------------------- /static/img/strictNullChecks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/strictNullChecks.png -------------------------------------------------------------------------------- /static/img/ts.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/img/tutorial/docsVersionDropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/tutorial/docsVersionDropdown.png -------------------------------------------------------------------------------- /static/img/tutorial/eslint/error-meaning.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/tutorial/eslint/error-meaning.ai -------------------------------------------------------------------------------- /static/img/tutorial/eslint/string-quotes-chart.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/tutorial/eslint/string-quotes-chart.ai -------------------------------------------------------------------------------- /static/img/tutorial/eslint/terminal-npx-eslint-src-airbnb-with-rules.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/tutorial/eslint/terminal-npx-eslint-src-airbnb-with-rules.ai -------------------------------------------------------------------------------- /static/img/tutorial/eslint/terminal-npx-eslint-src-airbnb.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/tutorial/eslint/terminal-npx-eslint-src-airbnb.ai -------------------------------------------------------------------------------- /static/img/tutorial/eslint/terminal-npx-eslint-src-semi.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/tutorial/eslint/terminal-npx-eslint-src-semi.ai -------------------------------------------------------------------------------- /static/img/tutorial/eslint/terminal-npx-eslint-src-typescript.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/tutorial/eslint/terminal-npx-eslint-src-typescript.ai -------------------------------------------------------------------------------- /static/img/tutorial/eslint/terminal-npx-eslint-src.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/tutorial/eslint/terminal-npx-eslint-src.ai -------------------------------------------------------------------------------- /static/img/tutorial/eslint/vscode-eslint-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/tutorial/eslint/vscode-eslint-example.png -------------------------------------------------------------------------------- /static/img/tutorial/eslint/vscode-marketplace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/tutorial/eslint/vscode-marketplace.png -------------------------------------------------------------------------------- /static/img/tutorial/eslint/webstorm-eslint-config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/tutorial/eslint/webstorm-eslint-config.png -------------------------------------------------------------------------------- /static/img/tutorial/eslint/webstorm-eslint-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/tutorial/eslint/webstorm-eslint-example.png -------------------------------------------------------------------------------- /static/img/tutorial/localeDropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/tutorial/localeDropdown.png -------------------------------------------------------------------------------- /static/img/why-you-should-use-typescript.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/img/why-you-should-use-typescript.png -------------------------------------------------------------------------------- /static/overview/ecosystem/typescript-ecosystem-map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/overview/ecosystem/typescript-ecosystem-map.png -------------------------------------------------------------------------------- /static/reference/values-types-variables/discriminated-union/summary-card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/reference/values-types-variables/discriminated-union/summary-card.png -------------------------------------------------------------------------------- /static/reference/values-types-variables/discriminated-union/summary-card@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/reference/values-types-variables/discriminated-union/summary-card@2x.png -------------------------------------------------------------------------------- /static/reference/values-types-variables/discriminated-union/summary-card@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/reference/values-types-variables/discriminated-union/summary-card@3x.png -------------------------------------------------------------------------------- /static/top/README.md: -------------------------------------------------------------------------------- 1 | # 画像アセット 2 | 3 | ここの画像アセットのソースはFigmaにあります。 4 | 5 | https://www.figma.com/file/E22NH0kgcl5xhVCtn1HCfz/%E3%82%B5%E3%83%90%E3%82%A4%E3%83%90%E3%83%ABTypeScript%E7%94%BB%E5%83%8F%E3%82%A2%E3%82%BB%E3%83%83%E3%83%88?type=design&node-id=501-29716&mode=design&t=odNRpyXYKCocVP7T-0 6 | -------------------------------------------------------------------------------- /static/tutorials/nextjs/nextjs-cat-image-display-result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/tutorials/nextjs/nextjs-cat-image-display-result.png -------------------------------------------------------------------------------- /static/tutorials/nextjs/nextjs-cat-image-generator-demo.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/tutorials/nextjs/nextjs-cat-image-generator-demo.mp4 -------------------------------------------------------------------------------- /static/tutorials/nextjs/nextjs-cat-image-refresh-demo.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/tutorials/nextjs/nextjs-cat-image-refresh-demo.mp4 -------------------------------------------------------------------------------- /static/tutorials/nextjs/nextjs-cat-placeholder-console-log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/tutorials/nextjs/nextjs-cat-placeholder-console-log.png -------------------------------------------------------------------------------- /static/tutorials/nextjs/nextjs-cat-placeholder-dark-mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/tutorials/nextjs/nextjs-cat-placeholder-dark-mode.png -------------------------------------------------------------------------------- /static/tutorials/nextjs/nextjs-initial-screen-dark-mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/tutorials/nextjs/nextjs-initial-screen-dark-mode.png -------------------------------------------------------------------------------- /static/tutorials/nextjs/nextjs-styled-cat-image-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yytypescript/book/a48a4147cabd90db334cbb765f76270c49cf8e21/static/tutorials/nextjs/nextjs-styled-cat-image-page.png -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // This file is not used in compilation. It is here just for a nice editor experience. 3 | "extends": "@tsconfig/docusaurus/tsconfig.json", 4 | "compilerOptions": { 5 | "module": "CommonJS", 6 | "target": "ES2015", 7 | "baseUrl": ".", 8 | "strict": true, 9 | "noUncheckedIndexedAccess": true, 10 | "moduleResolution": "node", 11 | "downlevelIteration": false, 12 | "checkJs": true, 13 | "skipLibCheck": true, 14 | "types": [ 15 | "node", 16 | "jest", 17 | "@docusaurus/module-type-aliases", 18 | "@docusaurus/theme-classic" 19 | ] 20 | }, 21 | "include": ["src/"], 22 | "exclude": [ 23 | "node_modules/", 24 | "src/components/codeReadingAssistant/sampleCodes" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /tsconfig.twoslash.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "compilerOptions": { 4 | "target": "es2016", 5 | "allowJs": true, 6 | "strict": true, 7 | "types": ["node", "css-modules"], 8 | "downlevelIteration": true 9 | } 10 | } 11 | --------------------------------------------------------------------------------