├── .github └── workflows │ ├── compile.sh │ ├── lint.sh │ └── validate-content.yml ├── .gitignore ├── LICENSE.MD ├── README-zh_CN.md ├── README.md ├── downloads ├── typescript-book-zh_CN.epub ├── typescript-book-zh_CN.pdf ├── typescript-book.epub └── typescript-book.pdf ├── tools ├── .markdownlint.json ├── .nvmrc ├── .prettierrc ├── .vscode │ ├── launch.json │ └── settings.json ├── Makefile ├── README.md ├── compile.ts ├── config.ts ├── format.ts ├── i18n.ts ├── lint.ts ├── make-books.sh ├── make-website-content.py ├── package-lock.json ├── package.json ├── test-md │ ├── README-zh_CN.md │ └── README.md ├── tsconfig.json └── utils.ts ├── website-astro ├── .gitignore ├── .prettierrc.json ├── astro.config.mjs ├── eslint.config.js ├── package.json ├── pnpm-lock.yaml ├── public │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ └── site.webmanifest ├── scripts │ └── gen.ts ├── src │ ├── components │ │ └── head.astro │ ├── content │ │ ├── config.ts │ │ └── docs │ │ │ ├── books │ │ │ ├── About the Author.md │ │ │ ├── Any type.md │ │ │ ├── Assignments.md │ │ │ ├── Built-in Type Primitives.md │ │ │ ├── Class.md │ │ │ ├── Common Built-in JS Objects.md │ │ │ ├── Conditional Types.md │ │ │ ├── Control Flow Analysis.md │ │ │ ├── Differences between Type and Interface.md │ │ │ ├── Discriminated Unions.md │ │ │ ├── Distributive Conditional Types.md │ │ │ ├── Enums.md │ │ │ ├── Erased Structural Types.md │ │ │ ├── Exhaustiveness checking.md │ │ │ ├── Exploring the Type System.md │ │ │ ├── Extending Types.md │ │ │ ├── Fixed Length Tuple.md │ │ │ ├── Generics.md │ │ │ ├── Getting Started With TypeScript.md │ │ │ ├── Index Signatures.md │ │ │ ├── Interface and Type.md │ │ │ ├── Intersection Types.md │ │ │ ├── Introduction.md │ │ │ ├── Literal Inference.md │ │ │ ├── Literal Types.md │ │ │ ├── Mapped Type Modifiers.md │ │ │ ├── Mapped Types.md │ │ │ ├── Merging and Extension.md │ │ │ ├── Named Tuple Type (Labeled).md │ │ │ ├── Namespacing.md │ │ │ ├── Narrowing.md │ │ │ ├── Never type.md │ │ │ ├── Object Types.md │ │ │ ├── Optional Properties.md │ │ │ ├── Others.md │ │ │ ├── Overloads.md │ │ │ ├── Predefined Conditional Types.md │ │ │ ├── Primitive Types.md │ │ │ ├── Readonly Properties.md │ │ │ ├── Symbols.md │ │ │ ├── Table of Contents.md │ │ │ ├── Template Union Types.md │ │ │ ├── The Concise TypeScript Book.md │ │ │ ├── The never Type.md │ │ │ ├── Triple-Slash Directives.md │ │ │ ├── Tuple Type (Anonymous).md │ │ │ ├── Type Annotations.md │ │ │ ├── Type Indexing.md │ │ │ ├── Type Manipulation.md │ │ │ ├── Type Predicates.md │ │ │ ├── Type from Func Return.md │ │ │ ├── Type from Module.md │ │ │ ├── Type from Value.md │ │ │ ├── TypeScript Introduction.md │ │ │ ├── Union Type.md │ │ │ ├── Unknown type.md │ │ │ ├── Void type.md │ │ │ ├── infer Type Inference in Conditional Types.md │ │ │ └── strictNullChecks.md │ │ │ ├── index.md │ │ │ └── zh-cn │ │ │ ├── books │ │ │ ├── About the Author.md │ │ │ ├── Any type.md │ │ │ ├── Assignments.md │ │ │ ├── Built-in Type Primitives.md │ │ │ ├── Class.md │ │ │ ├── Common Built-in JS Objects.md │ │ │ ├── Conditional Types.md │ │ │ ├── Control Flow Analysis.md │ │ │ ├── Differences between Type and Interface.md │ │ │ ├── Discriminated Unions.md │ │ │ ├── Distributive Conditional Types.md │ │ │ ├── Enums.md │ │ │ ├── Erased Structural Types.md │ │ │ ├── Exhaustiveness checking.md │ │ │ ├── Exploring the Type System.md │ │ │ ├── Extending Types.md │ │ │ ├── Fixed Length Tuple.md │ │ │ ├── Generics.md │ │ │ ├── Getting Started With TypeScript.md │ │ │ ├── Index Signatures.md │ │ │ ├── Interface and Type.md │ │ │ ├── Intersection Types.md │ │ │ ├── Introduction.md │ │ │ ├── Literal Inference.md │ │ │ ├── Literal Types.md │ │ │ ├── Mapped Type Modifiers.md │ │ │ ├── Mapped Types.md │ │ │ ├── Merging and Extension.md │ │ │ ├── Named Tuple Type (Labeled).md │ │ │ ├── Namespacing.md │ │ │ ├── Narrowing.md │ │ │ ├── Never type.md │ │ │ ├── Object Types.md │ │ │ ├── Optional Properties.md │ │ │ ├── Others.md │ │ │ ├── Overloads.md │ │ │ ├── Predefined Conditional Types.md │ │ │ ├── Primitive Types.md │ │ │ ├── Readonly Properties.md │ │ │ ├── Symbols.md │ │ │ ├── Table of Contents.md │ │ │ ├── Template Union Types.md │ │ │ ├── The Concise TypeScript Book.md │ │ │ ├── The never Type.md │ │ │ ├── Triple-Slash Directives.md │ │ │ ├── Tuple Type (Anonymous).md │ │ │ ├── Type Annotations.md │ │ │ ├── Type Indexing.md │ │ │ ├── Type Manipulation.md │ │ │ ├── Type Predicates.md │ │ │ ├── Type from Func Return.md │ │ │ ├── Type from Module.md │ │ │ ├── Type from Value.md │ │ │ ├── TypeScript Introduction.md │ │ │ ├── Union Type.md │ │ │ ├── Unknown type.md │ │ │ ├── Void type.md │ │ │ ├── infer Type Inference in Conditional Types.md │ │ │ └── strictNullChecks.md │ │ │ └── index.md │ ├── env.d.ts │ └── styles │ │ └── global.css ├── tailwind.config.ts └── tsconfig.json └── website ├── .gitignore ├── .nvmrc ├── .prettierrc ├── .vscode ├── extensions.json └── launch.json ├── README.md ├── astro.config.mjs ├── package-lock.json ├── package.json ├── public └── favicon.svg ├── src ├── assets │ └── houston.webp ├── content │ ├── config.ts │ ├── docs │ │ ├── book │ │ │ ├── about-the-author.md │ │ │ ├── any-type.md │ │ │ ├── assignments.md │ │ │ ├── built-in-type-primitives.md │ │ │ ├── class.md │ │ │ ├── common-built-in-js-objects.md │ │ │ ├── conditional-types.md │ │ │ ├── control-flow-analysis.md │ │ │ ├── differences-between-type-and-interface.md │ │ │ ├── discriminated-unions.md │ │ │ ├── distributive-conditional-types.md │ │ │ ├── downloads-and-website.md │ │ │ ├── enums.md │ │ │ ├── erased-structural-types.md │ │ │ ├── exhaustiveness-checking.md │ │ │ ├── exploring-the-type-system.md │ │ │ ├── extending-types.md │ │ │ ├── fixed-length-tuple.md │ │ │ ├── generics.md │ │ │ ├── getting-started-with-typescript.md │ │ │ ├── index-signatures.md │ │ │ ├── infer-type-inference-in-conditional-types.md │ │ │ ├── interface-and-type.md │ │ │ ├── intersection-types.md │ │ │ ├── introduction.md │ │ │ ├── literal-inference.md │ │ │ ├── literal-types.md │ │ │ ├── mapped-type-modifiers.md │ │ │ ├── mapped-types.md │ │ │ ├── merging-and-extension.md │ │ │ ├── named-tuple-type-labeled.md │ │ │ ├── namespacing.md │ │ │ ├── narrowing.md │ │ │ ├── never-type.md │ │ │ ├── object-types.md │ │ │ ├── optional-properties.md │ │ │ ├── others.md │ │ │ ├── overloads.md │ │ │ ├── predefined-conditional-types.md │ │ │ ├── primitive-types.md │ │ │ ├── readonly-properties.md │ │ │ ├── strictnullchecks.md │ │ │ ├── symbols.md │ │ │ ├── table-of-contents.md │ │ │ ├── template-union-types.md │ │ │ ├── the-concise-typescript-book.md │ │ │ ├── the-never-type.md │ │ │ ├── translations.md │ │ │ ├── triple-slash-directives.md │ │ │ ├── tuple-type-anonymous.md │ │ │ ├── type-annotations.md │ │ │ ├── type-from-func-return.md │ │ │ ├── type-from-module.md │ │ │ ├── type-from-value.md │ │ │ ├── type-indexing.md │ │ │ ├── type-manipulation.md │ │ │ ├── type-predicates.md │ │ │ ├── typescript-introduction.md │ │ │ ├── union-type.md │ │ │ ├── unknown-type.md │ │ │ └── void-type.md │ │ ├── index.mdx │ │ └── zh-cn │ │ │ ├── book │ │ │ ├── about-the-author.md │ │ │ ├── any-type.md │ │ │ ├── assignments.md │ │ │ ├── built-in-type-primitives.md │ │ │ ├── class.md │ │ │ ├── common-built-in-js-objects.md │ │ │ ├── conditional-types.md │ │ │ ├── control-flow-analysis.md │ │ │ ├── differences-between-type-and-interface.md │ │ │ ├── discriminated-unions.md │ │ │ ├── distributive-conditional-types.md │ │ │ ├── downloads-and-website.md │ │ │ ├── enums.md │ │ │ ├── erased-structural-types.md │ │ │ ├── exhaustiveness-checking.md │ │ │ ├── exploring-the-type-system.md │ │ │ ├── extending-types.md │ │ │ ├── fixed-length-tuple.md │ │ │ ├── generics.md │ │ │ ├── getting-started-with-typescript.md │ │ │ ├── index-signatures.md │ │ │ ├── infer-type-inference-in-conditional-types.md │ │ │ ├── interface-and-type.md │ │ │ ├── intersection-types.md │ │ │ ├── introduction.md │ │ │ ├── literal-inference.md │ │ │ ├── literal-types.md │ │ │ ├── mapped-type-modifiers.md │ │ │ ├── mapped-types.md │ │ │ ├── merging-and-extension.md │ │ │ ├── named-tuple-type-labeled.md │ │ │ ├── namespacing.md │ │ │ ├── narrowing.md │ │ │ ├── never-type.md │ │ │ ├── object-types.md │ │ │ ├── optional-properties.md │ │ │ ├── others.md │ │ │ ├── overloads.md │ │ │ ├── predefined-conditional-types.md │ │ │ ├── primitive-types.md │ │ │ ├── readonly-properties.md │ │ │ ├── strictnullchecks.md │ │ │ ├── symbols.md │ │ │ ├── table-of-contents.md │ │ │ ├── template-union-types.md │ │ │ ├── the-concise-typescript-book.md │ │ │ ├── the-never-type.md │ │ │ ├── translations.md │ │ │ ├── triple-slash-directives.md │ │ │ ├── tuple-type-anonymous.md │ │ │ ├── type-annotations.md │ │ │ ├── type-from-func-return.md │ │ │ ├── type-from-module.md │ │ │ ├── type-from-value.md │ │ │ ├── type-indexing.md │ │ │ ├── type-manipulation.md │ │ │ ├── type-predicates.md │ │ │ ├── typescript-introduction.md │ │ │ ├── union-type.md │ │ │ ├── unknown-type.md │ │ │ └── void-type.md │ │ │ └── index.mdx │ └── i18n │ │ └── zh-cn.json ├── env.d.ts └── styles │ └── custom.css └── tsconfig.json /.github/workflows/compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | echo "Compiling all code snippets ..." 4 | cd tools 5 | npm ci 6 | npm run compile -------------------------------------------------------------------------------- /.github/workflows/lint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | echo "Linting Markdown and Code files ..." 4 | cd tools 5 | npm ci 6 | npm run lint 7 | npm run lint:md -------------------------------------------------------------------------------- /.github/workflows/validate-content.yml: -------------------------------------------------------------------------------- 1 | name: validate-content 2 | run-name: ${{ github.actor }} validate content 3 | on: [pull_request] 4 | jobs: 5 | lint-content: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@v3 9 | - name: Run lint script 10 | run: bash ${GITHUB_WORKSPACE}/.github/workflows/lint.sh 11 | compile-snippets: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | - name: Run compile script 16 | run: bash ${GITHUB_WORKSPACE}/.github/workflows/compile.sh 17 | 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | temp 3 | !.vscode 4 | -------------------------------------------------------------------------------- /LICENSE.MD: -------------------------------------------------------------------------------- 1 | # Licence 2 | 3 | The Concise TypeScript Book © by Simone Poggiali is licensed under Attribution 4.0 International. 4 | 5 | For more information visit: 6 | 7 | -------------------------------------------------------------------------------- /downloads/typescript-book-zh_CN.epub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nnecec/typescript-book/f042af63e3471f5dc7e8f1450f87e0f57398f5e9/downloads/typescript-book-zh_CN.epub -------------------------------------------------------------------------------- /downloads/typescript-book-zh_CN.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nnecec/typescript-book/f042af63e3471f5dc7e8f1450f87e0f57398f5e9/downloads/typescript-book-zh_CN.pdf -------------------------------------------------------------------------------- /downloads/typescript-book.epub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nnecec/typescript-book/f042af63e3471f5dc7e8f1450f87e0f57398f5e9/downloads/typescript-book.epub -------------------------------------------------------------------------------- /downloads/typescript-book.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nnecec/typescript-book/f042af63e3471f5dc7e8f1450f87e0f57398f5e9/downloads/typescript-book.pdf -------------------------------------------------------------------------------- /tools/.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "code-block-style": { 3 | "style": "fenced" 4 | }, 5 | "code-fence-style": { 6 | "style": "backtick" 7 | }, 8 | "emphasis-style": { 9 | "style": "asterisk" 10 | }, 11 | "fenced-code-language": { 12 | "allowed_languages": [ 13 | "shell", 14 | "json", 15 | "typescript", 16 | "javascript", 17 | "text" 18 | ], 19 | "language_only": true 20 | }, 21 | "heading-style": { 22 | "style": "atx" 23 | }, 24 | "hr-style": { 25 | "style": "---" 26 | }, 27 | "line-length": false, 28 | "no-duplicate-heading": { 29 | "siblings_only": true 30 | }, 31 | "ol-prefix": { 32 | "style": "ordered" 33 | }, 34 | "proper-names": { 35 | "code_blocks": false, 36 | "names": [ 37 | "TypeScript", 38 | "Ctrl", 39 | "JavaScript", 40 | "Markdown", 41 | "Node.js", 42 | "Visual Studio Code", 43 | "Microsoft", 44 | "LinkedIn", 45 | "GitHub", 46 | "Twitter", 47 | "Email", 48 | "IntelliSense", 49 | "ECMAScript" 50 | ] 51 | }, 52 | "required-headings": false, 53 | "strong-style": { 54 | "style": "asterisk" 55 | }, 56 | "ul-style": { 57 | "style": "asterisk" 58 | } 59 | } -------------------------------------------------------------------------------- /tools/.nvmrc: -------------------------------------------------------------------------------- 1 | v19.7.0 2 | -------------------------------------------------------------------------------- /tools/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 4, 4 | "semi": true, 5 | "singleQuote": true, 6 | "printWidth": 80, 7 | "arrowParens": "avoid" 8 | } -------------------------------------------------------------------------------- /tools/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Debug lint", 6 | "type": "node", 7 | "request": "launch", 8 | "runtimeExecutable": "node", 9 | "runtimeArgs": [ 10 | "--nolazy", 11 | "-r", 12 | "${workspaceRoot}/node_modules/ts-node/register/transpile-only" 13 | ], 14 | "args": [ 15 | "lint.ts", 16 | "--example", 17 | "hello" 18 | ], 19 | "cwd": "${workspaceRoot}", 20 | "internalConsoleOptions": "openOnSessionStart", 21 | "skipFiles": [ 22 | "/**", 23 | "node_modules/**" 24 | ] 25 | }, 26 | { 27 | "name": "Python: Current File", 28 | "type": "python", 29 | "request": "launch", 30 | "program": "${file}", 31 | "console": "integratedTerminal", 32 | "justMyCode": true 33 | } 34 | ] 35 | } -------------------------------------------------------------------------------- /tools/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | } -------------------------------------------------------------------------------- /tools/Makefile: -------------------------------------------------------------------------------- 1 | format: 2 | npm run format 3 | 4 | check: 5 | npm run check 6 | 7 | website: 8 | python3 ./make-website-content.py 9 | 10 | website-deploy: 11 | cd ../website && npm run deploy 12 | 13 | website-preview: 14 | cd ../website && npm run build && npm run preview 15 | 16 | books: 17 | ./make-books.sh -------------------------------------------------------------------------------- /tools/config.ts: -------------------------------------------------------------------------------- 1 | export const PRETTIER_CONFIG_FILE_PATH = './.prettierrc' 2 | 3 | export const CODE_BLOCK_TS_REGEX = /```typescript([\s\S]*?)```/g; -------------------------------------------------------------------------------- /tools/format.ts: -------------------------------------------------------------------------------- 1 | import * as prettier from 'prettier'; 2 | import * as fs from 'fs'; 3 | import { Language, languages } from './i18n'; 4 | import { PrettierOptions, getPrettierOptions, makeFilePath } from './utils'; 5 | import { CODE_BLOCK_TS_REGEX } from './config'; 6 | 7 | const formatCodeBlocksInMarkdownFile = async (filePath: string, options: PrettierOptions, language: Language): Promise => { 8 | const markdown = await fs.promises.readFile(filePath, 'utf-8'); 9 | 10 | let formattedMarkdown = markdown; 11 | let match; 12 | while ((match = CODE_BLOCK_TS_REGEX.exec(markdown)) !== null) { 13 | const codeBlock = match[0]; 14 | const code = match[1].trim(); 15 | const formattedCode = await prettier.format(code, { 16 | parser: 'typescript', 17 | ...options, 18 | }); 19 | formattedMarkdown = formattedMarkdown.replace(codeBlock, `\`\`\`typescript\n${formattedCode}\`\`\``); 20 | } 21 | 22 | await fs.promises.writeFile(filePath, formattedMarkdown, 'utf-8'); 23 | console.log(`${language} Formatted code blocks have been updated in the file: ${filePath}`); 24 | } 25 | 26 | const main = async () => { 27 | const options = await getPrettierOptions() 28 | 29 | for (const language of languages) { 30 | formatCodeBlocksInMarkdownFile(makeFilePath(language), options, language); 31 | } 32 | } 33 | 34 | main() 35 | 36 | 37 | -------------------------------------------------------------------------------- /tools/i18n.ts: -------------------------------------------------------------------------------- 1 | export enum Language { 2 | en_EN = 'en_EN', 3 | zh_CN = 'zh_CN', 4 | } 5 | export type Languages = [Language.en_EN, Language.zh_CN] 6 | 7 | export const languages: Languages = [Language.en_EN, Language.zh_CN] -------------------------------------------------------------------------------- /tools/lint.ts: -------------------------------------------------------------------------------- 1 | import * as prettier from 'prettier'; 2 | import * as fs from 'fs'; 3 | import { Language, languages } from './i18n'; 4 | import { PrettierOptions, getPrettierOptions, makeFilePath } from './utils'; 5 | import { CODE_BLOCK_TS_REGEX } from './config'; 6 | 7 | const lintCodeBlocksInMarkdownFile = async (filePath: string, options: PrettierOptions, language: Language): Promise => { 8 | const markdown = await fs.promises.readFile(filePath, 'utf-8'); 9 | 10 | let reportSnippetsNotLinted = ''; 11 | let match; 12 | while ((match = CODE_BLOCK_TS_REGEX.exec(markdown)) !== null) { 13 | const code = match[1].trim() + '\n' 14 | const isCodeLinted = await prettier.check(code, { 15 | parser: 'typescript', 16 | ...options, 17 | }); 18 | if (isCodeLinted === false) { 19 | reportSnippetsNotLinted += code 20 | reportSnippetsNotLinted += '\n' 21 | } 22 | } 23 | if (reportSnippetsNotLinted.length === 0) { 24 | console.log(`${language} All snippets are linted!`) 25 | } else { 26 | console.error(`${language} Not all snippets are linted! Please use this command to automatically format the snippets: npm run format\n`) 27 | console.error(reportSnippetsNotLinted) 28 | process.exit(1) 29 | } 30 | } 31 | 32 | const main = async () => { 33 | const options = await getPrettierOptions() 34 | 35 | for (const language of languages) { 36 | lintCodeBlocksInMarkdownFile(makeFilePath(language), options, language); 37 | } 38 | } 39 | 40 | main() 41 | 42 | 43 | -------------------------------------------------------------------------------- /tools/make-books.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR_DOWNLOADS="downloads" 3 | 4 | INPUT_EN="README" 5 | INPUT_CN="README-zh_CN" 6 | 7 | OUTPUT_EN="typescript-book" 8 | OUTPUT_CN="typescript-book-zh_CN" 9 | 10 | AUTHOR="Simone Poggiali" 11 | TITLE_EN="The Concise TypeScript Book" 12 | TITLE_CN="# 简洁的TypeScript之书" 13 | 14 | cd ../ 15 | 16 | echo "Making ebooks ..." 17 | 18 | # Check dependencies 19 | if command -v pandoc &>/dev/null; then 20 | echo "pandoc is installed" 21 | else 22 | echo "You need to install pandoc. Please visit: https://pandoc.org/installing.html" 23 | exit 1 24 | fi 25 | if command -v epubcheck &>/dev/null; then 26 | echo "epubcheck is installed" 27 | else 28 | echo "You need to install epubcheck. Please visit: https://www.w3.org/publishing/epubcheck/docs/installation/" 29 | exit 1 30 | fi 31 | if command -v ebook-convert &>/dev/null; then 32 | echo "calibre is installed" 33 | else 34 | echo "You need to install calibre. Please visit: https://calibre-ebook.com/download" 35 | exit 1 36 | fi 37 | 38 | # Generate eBooks 39 | pandoc -o $DIR_DOWNLOADS/$OUTPUT_EN.epub --metadata title="$TITLE_EN" --metadata author="$AUTHOR" -s $INPUT_EN.md 40 | pandoc -o $DIR_DOWNLOADS/$OUTPUT_CN.epub --metadata title="$TITLE_CN" --metadata author="$AUTHOR" -s $INPUT_CN.md 41 | 42 | # Validate eBooks 43 | epubcheck $DIR_DOWNLOADS/$OUTPUT_CN.epub 44 | epubcheck $DIR_DOWNLOADS/$OUTPUT_CN.epub 45 | 46 | # Generate PDFs 47 | ebook-convert $DIR_DOWNLOADS/$OUTPUT_EN.epub $DIR_DOWNLOADS/$OUTPUT_EN.pdf --pdf-page-numbers 48 | ebook-convert $DIR_DOWNLOADS/$OUTPUT_CN.epub $DIR_DOWNLOADS/$OUTPUT_CN.pdf --pdf-page-numbers 49 | 50 | echo "Books were created. Please commit!" -------------------------------------------------------------------------------- /tools/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-book", 3 | "version": "1.0.0", 4 | "description": "The Concise TypeScript Book provides a comprehensive and succinct overview of TypeScript's capabilities. It offers clear explanations covering all aspects found in the latest version of the language, from its powerful type system to advanced features. Whether you're a beginner or an experienced developer, this book is an invaluable resource to enhance your understanding and proficiency in TypeScript.", 5 | "main": "index.js", 6 | "scripts": { 7 | "format": "ts-node format", 8 | "compile": "ts-node compile", 9 | "test": "echo \"Error: no test specified\" && exit 1", 10 | "lint": "ts-node lint", 11 | "lint:md": "markdownlint \"./*.md\" markdownlint \"../*.md\"", 12 | "check": "npm run lint:md && npm run format && npm run compile" 13 | }, 14 | "author": "", 15 | "license": "ISC", 16 | "devDependencies": { 17 | "@types/fs-extra": "^11.0.1", 18 | "@types/marked": "^5.0.0", 19 | "@types/node": "^20.3.1", 20 | "@types/prettier": "^2.7.3", 21 | "fp-ts": "^2.16.0", 22 | "fs-extra": "^11.1.1", 23 | "markdownlint-cli": "^0.35.0", 24 | "marked": "^5.1.0", 25 | "prettier": "^3.3.0", 26 | "ts-node": "^10.9.1", 27 | "typescript": "^5.4.5" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tools/test-md/README-zh_CN.md: -------------------------------------------------------------------------------- 1 | # 简洁 TypeScript 书 2 | TypeScript 有效开发简明指南。 **免费和开源**。 3 | ## 创建文件和文件夹 4 | 可使用 按钮访问文件资源管理器。 5 | ## 切换到另一个文件 6 | 您的所有文件和文件夹都在文件资源管理器中显示为树。 您可以通过单击树中的文件从一个文件切换到另一个文件。 7 | ### 新标题 8 | 一些家长内容。 9 | #### 嵌套内容 1 10 | 更多内容在这里。 11 | ##### 嵌套内容 2 12 | 内容甚至更多。 -------------------------------------------------------------------------------- /tools/test-md/README.md: -------------------------------------------------------------------------------- 1 | # The Concise TypeScript Book 2 | A Concise Guide to Effective Development in TypeScript. **Free and Open Source**. 3 | ## Create files and folders 4 | The file explorer is accessible using the button. 5 | ## Switch to another file 6 | All your files and folders are presented as a tree in the file explorer. You can switch from one to another by clicking a file in the tree. 7 | ### New title 8 | Some parent content. 9 | #### Nested content 1 10 | More content here. 11 | ##### Nested content 2 12 | Even more content. -------------------------------------------------------------------------------- /tools/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "module": "commonjs", 5 | "noImplicitAny": true, 6 | "esModuleInterop": true, 7 | "noEmitOnError": true, 8 | "moduleDetection": "force", 9 | "noUnusedLocals": false, 10 | "forceConsistentCasingInFileNames": true, 11 | "strict": true, 12 | "skipLibCheck": true, 13 | "lib": [ 14 | "es2022", 15 | "esnext.disposable", 16 | "esnext.decorators", 17 | "dom" 18 | ] 19 | } 20 | } -------------------------------------------------------------------------------- /tools/utils.ts: -------------------------------------------------------------------------------- 1 | import { PRETTIER_CONFIG_FILE_PATH } from "./config"; 2 | import { Language } from "./i18n"; 3 | import * as prettier from 'prettier'; 4 | 5 | export const makeFilePath = (item: Language) => 6 | item === Language.en_EN ? '../README.md' : `../README-${item}.md` 7 | 8 | export type PrettierOptions = Exclude 9 | 10 | export const getPrettierOptions = async (): Promise => { 11 | const options = await prettier.resolveConfig(PRETTIER_CONFIG_FILE_PATH) 12 | if (options === null) { 13 | throw `No Prettier options are found! Check your Prettier configuration file.` 14 | } 15 | return options 16 | } -------------------------------------------------------------------------------- /website-astro/.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | # generated types 4 | .astro/ 5 | 6 | # dependencies 7 | node_modules/ 8 | 9 | # logs 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | pnpm-debug.log* 14 | 15 | 16 | # environment variables 17 | .env 18 | .env.production 19 | 20 | # macOS-specific files 21 | .DS_Store 22 | -------------------------------------------------------------------------------- /website-astro/.prettierrc.json: -------------------------------------------------------------------------------- 1 | "@nnecec/prettier-config" 2 | -------------------------------------------------------------------------------- /website-astro/eslint.config.js: -------------------------------------------------------------------------------- 1 | import nnecec from '@nnecec/eslint-config' 2 | 3 | /** @type {import('eslint').Linter.FlatConfig[]} */ 4 | export default [ 5 | ...nnecec({ 6 | tailwindcss: true, 7 | typescript: true, 8 | }), 9 | { 10 | files: ['**/*.ts', '**/*.tsx'], 11 | rules: { 12 | '@typescript-eslint/no-explicit-any': 'off', 13 | }, 14 | }, 15 | ] 16 | -------------------------------------------------------------------------------- /website-astro/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "website", 3 | "version": "0.0.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "astro": "astro", 8 | "build": "astro check && astro build", 9 | "dev": "astro dev", 10 | "gen": "tsx scripts/gen.ts", 11 | "preview": "astro preview", 12 | "start": "astro dev" 13 | }, 14 | "dependencies": { 15 | "@astrojs/check": "^0.9.4", 16 | "@astrojs/partytown": "^2.1.2", 17 | "@astrojs/starlight": "^0.28.6", 18 | "@astrojs/starlight-tailwind": "^2.0.3", 19 | "@astrojs/tailwind": "^5.1.2", 20 | "astro": "^4.16.10", 21 | "react": "^18.3.1", 22 | "react-dom": "^18.3.1", 23 | "remark": "^15.0.1", 24 | "remark-frontmatter": "^5.0.0", 25 | "sharp": "^0.33.5", 26 | "tailwindcss": "^3.4.14", 27 | "typescript": "^5.6.3", 28 | "unist-util-visit": "^5.0.0" 29 | }, 30 | "devDependencies": { 31 | "@nnecec/eslint-config": "^0.11.0", 32 | "@nnecec/prettier-config": "^0.4.3", 33 | "tsx": "^4.19.2" 34 | }, 35 | "packageManager": "pnpm@9.12.3+sha512.cce0f9de9c5a7c95bef944169cc5dfe8741abfb145078c0d508b868056848a87c81e626246cb60967cbd7fd29a6c062ef73ff840d96b3c86c40ac92cf4a813ee" 36 | } 37 | -------------------------------------------------------------------------------- /website-astro/public/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nnecec/typescript-book/f042af63e3471f5dc7e8f1450f87e0f57398f5e9/website-astro/public/android-chrome-192x192.png -------------------------------------------------------------------------------- /website-astro/public/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nnecec/typescript-book/f042af63e3471f5dc7e8f1450f87e0f57398f5e9/website-astro/public/android-chrome-512x512.png -------------------------------------------------------------------------------- /website-astro/public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nnecec/typescript-book/f042af63e3471f5dc7e8f1450f87e0f57398f5e9/website-astro/public/apple-touch-icon.png -------------------------------------------------------------------------------- /website-astro/public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nnecec/typescript-book/f042af63e3471f5dc7e8f1450f87e0f57398f5e9/website-astro/public/favicon-16x16.png -------------------------------------------------------------------------------- /website-astro/public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nnecec/typescript-book/f042af63e3471f5dc7e8f1450f87e0f57398f5e9/website-astro/public/favicon-32x32.png -------------------------------------------------------------------------------- /website-astro/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nnecec/typescript-book/f042af63e3471f5dc7e8f1450f87e0f57398f5e9/website-astro/public/favicon.ico -------------------------------------------------------------------------------- /website-astro/public/site.webmanifest: -------------------------------------------------------------------------------- 1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} -------------------------------------------------------------------------------- /website-astro/src/components/head.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Props } from '@astrojs/starlight/props' 3 | import Default from '@astrojs/starlight/components/Head.astro' 4 | 5 | const gaId = import.meta.env.PUBLIC_GA_ID 6 | --- 7 | 8 | 10 | 18 | 19 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /website-astro/src/content/config.ts: -------------------------------------------------------------------------------- 1 | import { docsSchema, i18nSchema } from '@astrojs/starlight/schema' 2 | import { defineCollection } from 'astro:content' 3 | 4 | export const collections = { 5 | docs: defineCollection({ schema: docsSchema() }), 6 | i18n: defineCollection({ schema: i18nSchema(), type: 'data' }), 7 | } 8 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/About the Author.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: About the Author 3 | sidebar: 4 | order: 4 5 | label: 4. About the Author 6 | --- 7 | 8 | Simone Poggiali is an experienced Senior Front-end Developer with a passion for writing professional-grade code since the 90s. Throughout his international career, he has contributed to numerous projects for a wide range of clients, from startups to large organizations. Notable companies such as HelloFresh, Siemens, O2, and Leroy Merlin have benefited from his expertise and dedication. 9 | 10 | You can reach Simone Poggiali on the following platforms: 11 | 12 | * LinkedIn: 13 | * GitHub: 14 | * X.com: 15 | * Email: gibbok.coding📧gmail.com 16 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Any type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Any type 3 | sidebar: 4 | order: 42 5 | label: 42. Any type 6 | --- 7 | 8 | The `any` type is a special type (universal supertype) that can be used to represent any type of value (primitives, objects, arrays, functions, errors, symbols). It is often used in situations where the type of a value is not known at compile time, or when working with values from external APIs or libraries that do not have TypeScript typings. 9 | 10 | By utilizing `any` type, you are indicating to the TypeScript compiler that values should be represented without any limitations. In order to maximizing type safety in your code consider the following: 11 | 12 | * Limit the usage of `any` to specific cases where the type is truly unknown. 13 | * Do not return `any` types from a function as you will lose type safety in the code using that function weakening your type safety. 14 | * Instead of `any` use `@ts-ignore` if you need to silence the compiler. 15 | 16 | ```typescript 17 | let value: any; 18 | value = true; // Valid 19 | value = 7; // Valid 20 | ``` 21 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Assignments.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Assignments 3 | sidebar: 4 | order: 19 5 | label: 19. Assignments 6 | --- 7 | 8 | TypeScript narrowing using assignments is a way to narrow the type of a variable based on the value assigned to it. When a variable is assigned a value, TypeScript infers its type based on the assigned value, and it narrows the type of the variable to match the inferred type. 9 | 10 | ```typescript 11 | let value: string | number; 12 | value = 'hello'; 13 | if (typeof value === 'string') { 14 | console.log(value.toUpperCase()); 15 | } 16 | value = 42; 17 | if (typeof value === 'number') { 18 | console.log(value.toFixed(2)); 19 | } 20 | ``` 21 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Built-in Type Primitives.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Built-in Type Primitives 3 | sidebar: 4 | order: 47 5 | label: 47. Built-in Type Primitives 6 | --- 7 | 8 | TypeScript has several built-in type primitives that can be used to define variables, function parameters, and return types: 9 | 10 | * `number`: Represents numeric values, including integers and floating-point numbers. 11 | * `string`: Represents textual data 12 | * `boolean`: Represents logical values, which can be either true or false. 13 | * `null`: Represents the absence of a value. 14 | * `undefined`: Represents a value that has not been assigned or has not been defined. 15 | * `symbol`: Represents a unique identifier. Symbols are typically used as keys for object properties. 16 | * `bigint`: Represents arbitrary-precision integers. 17 | * `any`: Represents a dynamic or unknown type. Variables of type any can hold values of any type, and they bypass type checking. 18 | * `void`: Represents the absence of any type. It is commonly used as the return type of functions that do not return a value. 19 | * `never`: Represents a type for values that never occur. It is typically used as the return type of functions that throw an error or enter an infinite loop. 20 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Common Built-in JS Objects.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Common Built-in JS Objects 3 | sidebar: 4 | order: 48 5 | label: 48. Common Built-in JS Objects 6 | --- 7 | 8 | TypeScript is a superset of JavaScript, it includes all the commonly used built-in JavaScript objects. You can find an extensive list of these objects on the Mozilla Developer Network (MDN) documentation website: 9 | 10 | 11 | Here is a list of some commonly used built-in JavaScript objects: 12 | 13 | * Function 14 | * Object 15 | * Boolean 16 | * Error 17 | * Number 18 | * BigInt 19 | * Math 20 | * Date 21 | * String 22 | * RegExp 23 | * Array 24 | * Map 25 | * Set 26 | * Promise 27 | * Intl 28 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Conditional Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Conditional Types 3 | sidebar: 4 | order: 37 5 | label: 37. Conditional Types 6 | --- 7 | 8 | Conditional Types are a way to create a type that depends on a condition, where the type to be created is determined based on the result of the condition. They are defined using the `extends` keyword and a ternary operator to conditionally choose between two types. 9 | 10 | ```typescript 11 | type IsArray = T extends any[] ? true : false; 12 | 13 | const myArray = [1, 2, 3]; 14 | const myNumber = 42; 15 | 16 | type IsMyArrayAnArray = IsArray; // Type true 17 | type IsMyNumberAnArray = IsArray; // Type false 18 | ``` 19 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Control Flow Analysis.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Control Flow Analysis 3 | sidebar: 4 | order: 20 5 | label: 20. Control Flow Analysis 6 | --- 7 | 8 | Control Flow Analysis in TypeScript is a way to statically analyze the code flow to infer the types of variables, allowing the compiler to narrow the types of those variables as needed, based on the results of the analysis. 9 | 10 | Prior to TypeScript 4.4, code flow analysis would only be applied to code within an if statement, but from TypeScript 4.4, it can also be applied to conditional expressions and discriminant property accesses indirectly referenced through const variables. 11 | 12 | For example: 13 | 14 | ```typescript 15 | const f1 = (x: unknown) => { 16 | const isString = typeof x === 'string'; 17 | if (isString) { 18 | x.length; 19 | } 20 | }; 21 | 22 | const f2 = ( 23 | obj: { kind: 'foo'; foo: string } | { kind: 'bar'; bar: number } 24 | ) => { 25 | const isFoo = obj.kind === 'foo'; 26 | if (isFoo) { 27 | obj.foo; 28 | } else { 29 | obj.bar; 30 | } 31 | }; 32 | ``` 33 | 34 | Some examples where narrowing does not occur: 35 | 36 | 37 | 38 | ```typescript 39 | const f1 = (x: unknown) => { 40 | let isString = typeof x === 'string'; 41 | if (isString) { 42 | x.length; // Error, no narrowing because isString it is not const 43 | } 44 | }; 45 | 46 | const f6 = ( 47 | obj: { kind: 'foo'; foo: string } | { kind: 'bar'; bar: number } 48 | ) => { 49 | const isFoo = obj.kind === 'foo'; 50 | obj = obj; 51 | if (isFoo) { 52 | obj.foo; // Error, no narrowing because obj is assigned in function body 53 | } 54 | }; 55 | ``` 56 | 57 | Notes: Up to five levels of indirection are analyzed in conditional expressions. 58 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Differences between Type and Interface.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Differences between Type and Interface 3 | sidebar: 4 | order: 51 5 | label: 51. Differences between Type and Interface 6 | --- 7 | 8 | Declaration merging (augmentation): 9 | 10 | Interfaces support declaration merging, which means that you can define multiple interfaces with the same name, and TypeScript will merge them into a single interface with the combined properties and methods. On the other hand, types do not support declaration merging. This can be helpful when you want to add extra functionality or customize existing types without modifying the original definitions or patching missing or incorrect types. 11 | 12 | ```typescript 13 | interface A { 14 | x: string; 15 | } 16 | interface A { 17 | y: string; 18 | } 19 | const j: A = { 20 | x: 'xx', 21 | y: 'yy', 22 | }; 23 | ``` 24 | 25 | Extending other types/interfaces: 26 | 27 | Both types and interfaces can extend other types/interfaces, but the syntax is different. With interfaces, you use the `extends` keyword to inherit properties and methods from other interfaces. However, an interface cannot extend a complex type like a union type. 28 | 29 | ```typescript 30 | interface A { 31 | x: string; 32 | y: number; 33 | } 34 | interface B extends A { 35 | z: string; 36 | } 37 | const car: B = { 38 | x: 'x', 39 | y: 123, 40 | z: 'z', 41 | }; 42 | ``` 43 | 44 | For types, you use the & operator to combine multiple types into a single type (intersection). 45 | 46 | ```typescript 47 | interface A { 48 | x: string; 49 | y: number; 50 | } 51 | 52 | type B = A & { 53 | j: string; 54 | }; 55 | 56 | const c: B = { 57 | x: 'x', 58 | y: 123, 59 | j: 'j', 60 | }; 61 | ``` 62 | 63 | Union and Intersection Types: 64 | 65 | Types are more flexible when it comes to defining Union and Intersection Types. With the `type` keyword, you can easily create union types using the `|` operator and intersection types using the `&` operator. While interfaces can also represent union types indirectly, they don't have built-in support for intersection types. 66 | 67 | ```typescript 68 | type Department = 'dep-x' | 'dep-y'; // Union 69 | 70 | type Person = { 71 | name: string; 72 | age: number; 73 | }; 74 | 75 | type Employee = { 76 | id: number; 77 | department: Department; 78 | }; 79 | 80 | type EmployeeInfo = Person & Employee; // Intersection 81 | ``` 82 | 83 | Example with interfaces: 84 | 85 | ```typescript 86 | interface A { 87 | x: 'x'; 88 | } 89 | interface B { 90 | y: 'y'; 91 | } 92 | 93 | type C = A | B; // Union of interfaces 94 | ``` 95 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Discriminated Unions.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Discriminated Unions 3 | sidebar: 4 | order: 22 5 | label: 22. Discriminated Unions 6 | --- 7 | 8 | Discriminated Unions in TypeScript are a type of union type that uses a common property, known as the discriminant, to narrow down the set of possible types for the union. 9 | 10 | ```typescript 11 | type Square = { 12 | kind: 'square'; // Discriminant 13 | size: number; 14 | }; 15 | 16 | type Circle = { 17 | kind: 'circle'; // Discriminant 18 | radius: number; 19 | }; 20 | 21 | type Shape = Square | Circle; 22 | 23 | const area = (shape: Shape) => { 24 | switch (shape.kind) { 25 | case 'square': 26 | return Math.pow(shape.size, 2); 27 | case 'circle': 28 | return Math.PI * Math.pow(shape.radius, 2); 29 | } 30 | }; 31 | 32 | const square: Square = { kind: 'square', size: 5 }; 33 | const circle: Circle = { kind: 'circle', radius: 2 }; 34 | 35 | console.log(area(square)); // 25 36 | console.log(area(circle)); // 12.566370614359172 37 | ``` 38 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Distributive Conditional Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Distributive Conditional Types 3 | sidebar: 4 | order: 38 5 | label: 38. Distributive Conditional Types 6 | --- 7 | 8 | Distributive Conditional Types are a feature that allow a type to be distributed over a union of types, by applying a transformation to each member of the union individually. 9 | This can be especially useful when working with mapped types or higher-order types. 10 | 11 | ```typescript 12 | type Nullable = T extends any ? T | null : never; 13 | type NumberOrBool = number | boolean; 14 | type NullableNumberOrBool = Nullable; // number | boolean | null 15 | ``` 16 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Erased Structural Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Erased Structural Types 3 | sidebar: 4 | order: 54 5 | label: 54. Erased Structural Types 6 | --- 7 | 8 | In TypeScript, objects do not have to match a specific, exact type. For instance, if we create an object that fulfills an interface's requirements, we can utilize that object in places where that interface is required, even if there was no explicit connection between them. 9 | Example: 10 | 11 | ```typescript 12 | type NameProp1 = { 13 | prop1: string; 14 | }; 15 | 16 | function log(x: NameProp1) { 17 | console.log(x.prop1); 18 | } 19 | 20 | const obj = { 21 | prop2: 123, 22 | prop1: 'Origin', 23 | }; 24 | 25 | log(obj); // Valid 26 | ``` 27 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Exhaustiveness checking.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Exhaustiveness checking 3 | sidebar: 4 | order: 24 5 | label: 24. Exhaustiveness checking 6 | --- 7 | 8 | Exhaustiveness checking is a feature in TypeScript that ensures all possible cases of a discriminated union are handled in a `switch` statement or an `if` statement. 9 | 10 | ```typescript 11 | type Direction = 'up' | 'down'; 12 | 13 | const move = (direction: Direction) => { 14 | switch (direction) { 15 | case 'up': 16 | console.log('Moving up'); 17 | break; 18 | case 'down': 19 | console.log('Moving down'); 20 | break; 21 | default: 22 | const exhaustiveCheck: never = direction; 23 | console.log(exhaustiveCheck); // This line will never be executed 24 | } 25 | }; 26 | ``` 27 | 28 | The `never` type is used to ensure that the default case is exhaustive and that TypeScript will raise an error if a new value is added to the Direction type without being handled in the switch statement. 29 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Extending Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Extending Types 3 | sidebar: 4 | order: 13 5 | label: 13. Extending Types 6 | --- 7 | 8 | It is possible to extend an `interface` (copy members from another type): 9 | 10 | ```typescript 11 | interface X { 12 | a: string; 13 | } 14 | interface Y extends X { 15 | b: string; 16 | } 17 | ``` 18 | 19 | It is also possible to extend from multiple types: 20 | 21 | ```typescript 22 | interface A { 23 | a: string; 24 | } 25 | interface B { 26 | b: string; 27 | } 28 | interface Y extends A, B { 29 | y: string; 30 | } 31 | ``` 32 | 33 | The `extends` keyword works only on interfaces and classes, for types use an intersection: 34 | 35 | ```typescript 36 | type A = { 37 | a: number; 38 | }; 39 | type B = { 40 | b: number; 41 | }; 42 | type C = A & B; 43 | ``` 44 | 45 | It is possible to extend a type using an inference but not vice versa: 46 | 47 | ```typescript 48 | type A = { 49 | a: string; 50 | }; 51 | interface B extends A { 52 | b: string; 53 | } 54 | ``` 55 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Fixed Length Tuple.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Fixed Length Tuple 3 | sidebar: 4 | order: 28 5 | label: 28. Fixed Length Tuple 6 | --- 7 | 8 | A Fixed Length Tuple is a specific type of tuple that enforces a fixed number of elements of specific types, and disallows any modifications to the length of the tuple once it is defined. 9 | 10 | Fixed Length Tuples are useful when you need to represent a collection of values with a specific number of elements and specific types, and you want to ensure that the length and types of the tuple cannot be changed inadvertently. 11 | 12 | 13 | 14 | ```typescript 15 | const x = [10, 'hello'] as const; 16 | x.push(2); // Error 17 | ``` 18 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Index Signatures.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Index Signatures 3 | sidebar: 4 | order: 12 5 | label: 12. Index Signatures 6 | --- 7 | 8 | In TypeScript we can use as index signature `string`, `number`, and `symbol`: 9 | 10 | ```typescript 11 | type K = { 12 | [name: string | number]: string; 13 | }; 14 | const k: K = { x: 'x', 1: 'b' }; 15 | console.log(k['x']); 16 | console.log(k[1]); 17 | console.log(k['1']); // Same result as k[1] 18 | ``` 19 | 20 | Please note that JavaScript automatically converts an index with `number` to an index with `string` so `k[1]` or `k["1"]` return the same value. 21 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Interface and Type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Interface and Type 3 | sidebar: 4 | order: 46 5 | label: 46. Interface and Type 6 | --- 7 | 8 | ### Common Syntax 9 | 10 | In TypeScript, interfaces define the structure of objects, specifying the names and types of properties or methods that an object must have. The common syntax for defining an interface in TypeScript is as follows: 11 | 12 | 13 | 14 | ```typescript 15 | interface InterfaceName { 16 | property1: Type1; 17 | // ... 18 | method1(arg1: ArgType1, arg2: ArgType2): ReturnType; 19 | // ... 20 | } 21 | ``` 22 | 23 | Similarly for type definition: 24 | 25 | 26 | 27 | ```typescript 28 | type TypeName = { 29 | property1: Type1; 30 | // ... 31 | method1(arg1: ArgType1, arg2: ArgType2): ReturnType; 32 | // ... 33 | }; 34 | ``` 35 | 36 | `interface InterfaceName` or `type TypeName`: Defines the name of the interface. 37 | `property1`: `Type1`: Specifies the properties of the interface along with their corresponding types. Multiple properties can be defined, each separated by a semicolon. 38 | `method1(arg1: ArgType1, arg2: ArgType2): ReturnType;`: Specifies the methods of the interface. Methods are defined with their names, followed by a parameter list in parentheses and the return type. Multiple methods can be defined, each separated by a semicolon. 39 | 40 | Example interface: 41 | 42 | ```typescript 43 | interface Person { 44 | name: string; 45 | age: number; 46 | greet(): void; 47 | } 48 | ``` 49 | 50 | Example of type: 51 | 52 | ```typescript 53 | type TypeName = { 54 | property1: string; 55 | method1(arg1: string, arg2: string): string; 56 | }; 57 | ``` 58 | 59 | In TypeScript, types are used to define the shape of data and enforce type checking. There are several common syntaxes for defining types in TypeScript, depending on the specific use case. Here are some examples: 60 | 61 | ### Basic Types 62 | 63 | ```typescript 64 | let myNumber: number = 123; // number type 65 | let myBoolean: boolean = true; // boolean type 66 | let myArray: string[] = ['a', 'b']; // array of strings 67 | let myTuple: [string, number] = ['a', 123]; // tuple 68 | ``` 69 | 70 | ### Objects and Interfaces 71 | 72 | ```typescript 73 | const x: { name: string; age: number } = { name: 'Simon', age: 7 }; 74 | ``` 75 | 76 | ### Union and Intersection Types 77 | 78 | ```typescript 79 | type MyType = string | number; // Union type 80 | let myUnion: MyType = 'hello'; // Can be a string 81 | myUnion = 123; // Or a number 82 | 83 | type TypeA = { name: string }; 84 | type TypeB = { age: number }; 85 | type CombinedType = TypeA & TypeB; // Intersection type 86 | let myCombined: CombinedType = { name: 'John', age: 25 }; // Object with both name and age properties 87 | ``` 88 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Intersection Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Intersection Types 3 | sidebar: 4 | order: 30 5 | label: 30. Intersection Types 6 | --- 7 | 8 | An Intersection Type is a type that represents a value that has all the properties of two or more types. Intersection Types are denoted using the `&` symbol between each type. 9 | 10 | ```typescript 11 | type X = { 12 | a: string; 13 | }; 14 | 15 | type Y = { 16 | b: string; 17 | }; 18 | 19 | type J = X & Y; // Intersection 20 | 21 | const j: J = { 22 | a: 'a', 23 | b: 'b', 24 | }; 25 | ``` 26 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction 3 | sidebar: 4 | order: 3 5 | label: 3. Introduction 6 | --- 7 | 8 | Welcome to The Concise TypeScript Book! This guide equips you with essential knowledge and practical skills for effective TypeScript development. Discover key concepts and techniques to write clean, robust code. Whether you're a beginner or an experienced developer, this book serves as both a comprehensive guide and a handy reference for leveraging TypeScript's power in your projects. 9 | 10 | This book covers TypeScript 5.2. 11 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Literal Inference.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Literal Inference 3 | sidebar: 4 | order: 15 5 | label: 15. Literal Inference 6 | --- 7 | 8 | Literal Inference is a feature in TypeScript that allows the type of a variable or parameter to be inferred based on its value. 9 | 10 | In the following example we can see that TypeScript considers `x` a literal type as the value cannot be changed any time later, when instead `y` is inferred as string as it can be modified any time later. 11 | 12 | ```typescript 13 | const x = 'x'; // Literal type of 'x', because this value cannot be changed 14 | let y = 'y'; // Type string, as we can change this value 15 | ``` 16 | 17 | In the following example we can see that `o.x` was inferred as a `string` (and not a literal of `a`) as TypeScript considers that the value can be changed any time later. 18 | 19 | 20 | 21 | ```typescript 22 | type X = 'a' | 'b'; 23 | 24 | let o = { 25 | x: 'a', // This is a wider string 26 | }; 27 | 28 | const fn = (x: X) => `${x}-foo`; 29 | 30 | console.log(fn(o.x)); // Argument of type 'string' is not assignable to parameter of type 'X' 31 | ``` 32 | 33 | As you can see the code throws an error when passing `o.x` to `fn` as X is a narrower type. 34 | 35 | We can solve this issue by using type assertion using `const` or the `X` type: 36 | 37 | 38 | 39 | ```typescript 40 | let o = { 41 | x: 'a' as const, 42 | }; 43 | ``` 44 | 45 | or: 46 | 47 | 48 | 49 | ```typescript 50 | let o = { 51 | x: 'a' as X, 52 | }; 53 | ``` 54 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Literal Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Literal Types 3 | sidebar: 4 | order: 14 5 | label: 14. Literal Types 6 | --- 7 | 8 | A Literal Type is a single element set from a collective type, it defines a very exact value that is a JavaScript primitive. 9 | 10 | Literal Types in TypeScript are numbers, strings, and booleans. 11 | 12 | Example of literals: 13 | 14 | ```typescript 15 | const a = 'a'; // String literal type 16 | const b = 1; // Numeric literal type 17 | const c = true; // Boolean literal type 18 | ``` 19 | 20 | String, Numeric, and Boolean Literal Types are used in the union, type guard, and type aliases. 21 | In the following example you can see a type alias union, `O` can be the only value specified and not any other string: 22 | 23 | ```typescript 24 | type O = 'a' | 'b' | 'c'; 25 | ``` 26 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Mapped Type Modifiers.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Mapped Type Modifiers 3 | sidebar: 4 | order: 36 5 | label: 36. Mapped Type Modifiers 6 | --- 7 | 8 | Mapped Type Modifiers in TypeScript enable the transformation of properties within an existing type: 9 | 10 | * `readonly` or `+readonly`: This renders a property in the mapped type as read-only. 11 | * `-readonly`: This allows a property in the mapped type to be mutable. 12 | * `?`: This designates a property in the mapped type as optional. 13 | 14 | Examples: 15 | 16 | ```typescript 17 | type ReadOnly = { readonly [P in keyof T]: T[P] }; // All properties marked as read-only 18 | 19 | type Mutable = { -readonly [P in keyof T]: T[P] }; // All properties marked as mutable 20 | 21 | type MyPartial = { [P in keyof T]?: T[P] }; // All properties marked as optional 22 | ``` 23 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Mapped Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Mapped Types 3 | sidebar: 4 | order: 35 5 | label: 35. Mapped Types 6 | --- 7 | 8 | Mapped Types in TypeScript allow you to create new types based on an existing type by transforming each property using a mapping function. By mapping existing types, you can create new types that represent the same information in a different format. To create a mapped type, you access the properties of an existing type using the `keyof` operator and then alter them to produce a new type. 9 | In the following example: 10 | 11 | ```typescript 12 | type MyMappedType = { 13 | [P in keyof T]: T[P][]; 14 | }; 15 | type MyType = { 16 | foo: string; 17 | bar: number; 18 | }; 19 | type MyNewType = MyMappedType; 20 | const x: MyNewType = { 21 | foo: ['hello', 'world'], 22 | bar: [1, 2, 3], 23 | }; 24 | ``` 25 | 26 | we define MyMappedType to map over T's properties, creating a new type with each property as an array of its original type. Using this, we create MyNewType to represent the same info as MyType, but with each property as an array. 27 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Merging and Extension.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Merging and Extension 3 | sidebar: 4 | order: 50 5 | label: 50. Merging and Extension 6 | --- 7 | 8 | Merging and extension refer to two different concepts related to working with types and interfaces. 9 | 10 | Merging allows you to combine multiple declarations of the same name into a single definition, for example, when you define an interface with the same name multiple times: 11 | 12 | ```typescript 13 | interface X { 14 | a: string; 15 | } 16 | 17 | interface X { 18 | b: number; 19 | } 20 | 21 | const person: X = { 22 | a: 'a', 23 | b: 7, 24 | }; 25 | ``` 26 | 27 | Extension refers to the ability to extend or inherit from existing types or interfaces to create new ones. It is a mechanism to add additional properties or methods to an existing type without modifying its original definition. Example: 28 | 29 | ```typescript 30 | interface Animal { 31 | name: string; 32 | eat(): void; 33 | } 34 | 35 | interface Bird extends Animal { 36 | sing(): void; 37 | } 38 | 39 | const dog: Bird = { 40 | name: 'Bird 1', 41 | eat() { 42 | console.log('Eating'); 43 | }, 44 | sing() { 45 | console.log('Singing'); 46 | }, 47 | }; 48 | ``` 49 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Named Tuple Type (Labeled).md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Named Tuple Type (Labeled) 3 | sidebar: 4 | order: 27 5 | label: 27. Named Tuple Type (Labeled) 6 | --- 7 | 8 | Tuple types can include optional labels or names for each element. These labels are for readability and tooling assistance, and do not affect the operations you can perform with them. 9 | 10 | ```typescript 11 | type T = string; 12 | type Tuple1 = [T, T]; 13 | type Tuple2 = [a: T, b: T]; 14 | type Tuple3 = [a: T, T]; // Named Tuple plus Anonymous Tuple 15 | ``` 16 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Namespacing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Namespacing 3 | sidebar: 4 | order: 55 5 | label: 55. Namespacing 6 | --- 7 | 8 | In TypeScript, namespaces are used to organize code into logical containers, preventing naming collisions and providing a way to group related code together. 9 | The usage of the `export` keywords allows access to the namespace in "outside" modules. 10 | 11 | ```typescript 12 | export namespace MyNamespace { 13 | export interface MyInterface1 { 14 | prop1: boolean; 15 | } 16 | export interface MyInterface2 { 17 | prop2: string; 18 | } 19 | } 20 | 21 | const a: MyNamespace.MyInterface1 = { 22 | prop1: true, 23 | }; 24 | ``` 25 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Never type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Never type 3 | sidebar: 4 | order: 45 5 | label: 45. Never type 6 | --- 7 | 8 | The `never` type represents values that never occur. It is used to denote functions or expressions that never return or throw an error. 9 | 10 | For instance an infinite loop: 11 | 12 | ```typescript 13 | const infiniteLoop = (): never => { 14 | while (true) { 15 | // do something 16 | } 17 | }; 18 | ``` 19 | 20 | Throwing an error: 21 | 22 | ```typescript 23 | const throwError = (message: string): never => { 24 | throw new Error(message); 25 | }; 26 | ``` 27 | 28 | The `never` type is useful in ensuring type safety and catching potential errors in your code. It helps TypeScript analyze and infer more precise types when used in combination with other types and control flow statements, for instance: 29 | 30 | ```typescript 31 | type Direction = 'up' | 'down'; 32 | const move = (direction: Direction): void => { 33 | switch (direction) { 34 | case 'up': 35 | // move up 36 | break; 37 | case 'down': 38 | // move down 39 | break; 40 | default: 41 | const exhaustiveCheck: never = direction; 42 | throw new Error(`Unhandled direction: ${exhaustiveCheck}`); 43 | } 44 | }; 45 | ``` 46 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Object Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Object Types 3 | sidebar: 4 | order: 25 5 | label: 25. Object Types 6 | --- 7 | 8 | In TypeScript, object types describe the shape of an object. They specify the names and types of the object's properties, as well as whether those properties are required or optional. 9 | 10 | In TypeScript, you can define object types in two primary ways: 11 | 12 | Interface which defines the shape of an object by specifying the names, types, and optionality of its properties. 13 | 14 | ```typescript 15 | interface User { 16 | name: string; 17 | age: number; 18 | email?: string; 19 | } 20 | ``` 21 | 22 | Type alias, similar to an interface, defines the shape of an object. However, it can also create a new custom type that is based on an existing type or a combination of existing types. This includes defining union types, intersection types, and other complex types. 23 | 24 | ```typescript 25 | type Point = { 26 | x: number; 27 | y: number; 28 | }; 29 | ``` 30 | 31 | It also possible to define a type anonymously: 32 | 33 | ```typescript 34 | const sum = (x: { a: number; b: number }) => x.a + x.b; 35 | console.log(sum({ a: 5, b: 1 })); 36 | ``` 37 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Optional Properties.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Optional Properties 3 | sidebar: 4 | order: 10 5 | label: 10. Optional Properties 6 | --- 7 | 8 | An object can specify Optional Properties by adding a question mark `?` to the end of the property name: 9 | 10 | ```typescript 11 | type X = { 12 | a: number; 13 | b?: number; // Optional 14 | }; 15 | ``` 16 | 17 | It is possible to specify a default value when a property is optional" 18 | 19 | ```typescript 20 | type X = { 21 | a: number; 22 | b?: number; 23 | }; 24 | const x = ({ a, b = 100 }: X) => a + b; 25 | ``` 26 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Overloads.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Overloads 3 | sidebar: 4 | order: 49 5 | label: 49. Overloads 6 | --- 7 | 8 | Function overloads in TypeScript allow you to define multiple function signatures for a single function name, enabling you to define functions that can be called in multiple ways. Here's an example: 9 | 10 | ```typescript 11 | // Overloads 12 | function sayHi(name: string): string; 13 | function sayHi(names: string[]): string[]; 14 | 15 | // Implementation 16 | function sayHi(name: unknown): unknown { 17 | if (typeof name === 'string') { 18 | return `Hi, ${name}!`; 19 | } else if (Array.isArray(name)) { 20 | return name.map(name => `Hi, ${name}!`); 21 | } 22 | throw new Error('Invalid value'); 23 | } 24 | 25 | sayHi('xx'); // Valid 26 | sayHi(['aa', 'bb']); // Valid 27 | ``` 28 | 29 | Here's another example of using function overloads within a `class`: 30 | 31 | ```typescript 32 | class Greeter { 33 | message: string; 34 | 35 | constructor(message: string) { 36 | this.message = message; 37 | } 38 | 39 | // overload 40 | sayHi(name: string): string; 41 | sayHi(names: string[]): ReadonlyArray; 42 | 43 | // implementation 44 | sayHi(name: unknown): unknown { 45 | if (typeof name === 'string') { 46 | return `${this.message}, ${name}!`; 47 | } else if (Array.isArray(name)) { 48 | return name.map(name => `${this.message}, ${name}!`); 49 | } 50 | throw new Error('value is invalid'); 51 | } 52 | } 53 | console.log(new Greeter('Hello').sayHi('Simon')); 54 | ``` 55 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Predefined Conditional Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Predefined Conditional Types 3 | sidebar: 4 | order: 40 5 | label: 40. Predefined Conditional Types 6 | --- 7 | 8 | In TypeScript, Predefined Conditional Types are built-in conditional types provided by the language. They are designed to perform common type transformations based on the characteristics of a given type. 9 | 10 | `Exclude`: This type removes all the types from Type that are assignable to ExcludedType. 11 | 12 | `Extract`: This type extracts all the types from Union that are assignable to Type. 13 | 14 | `NonNullable`: This type removes null and undefined from Type. 15 | 16 | `ReturnType`: This type extracts the return type of a function Type. 17 | 18 | `Parameters`: This type extracts the parameter types of a function Type. 19 | 20 | `Required`: This type makes all properties in Type required. 21 | 22 | `Partial`: This type makes all properties in Type optional. 23 | 24 | `Readonly`: This type makes all properties in Type readonly. 25 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Readonly Properties.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Readonly Properties 3 | sidebar: 4 | order: 11 5 | label: 11. Readonly Properties 6 | --- 7 | 8 | Is it possible to prevent writing on a property by using the modifier `readonly`which makes sure that the property cannot be re-written but does not provide any guarantee of total immutability: 9 | 10 | ```typescript 11 | interface Y { 12 | readonly a: number; 13 | } 14 | 15 | type X = { 16 | readonly a: number; 17 | }; 18 | 19 | type J = Readonly<{ 20 | a: number; 21 | }>; 22 | 23 | type K = { 24 | readonly [index: number]: string; 25 | }; 26 | ``` 27 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Symbols.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Symbols 3 | sidebar: 4 | order: 56 5 | label: 56. Symbols 6 | --- 7 | 8 | Symbols are a primitive data type that represents an immutable value which is guaranteed to be globally unique throughout the lifetime of the program. 9 | 10 | Symbols can be used as keys for object properties and provide a way to create non-enumerable properties. 11 | 12 | ```typescript 13 | const key1: symbol = Symbol('key1'); 14 | const key2: symbol = Symbol('key2'); 15 | 16 | const obj = { 17 | [key1]: 'value 1', 18 | [key2]: 'value 2', 19 | }; 20 | 21 | console.log(obj[key1]); // value 1 22 | console.log(obj[key2]); // value 2 23 | ``` 24 | 25 | In WeakMaps and WeakSets, symbols are now permissible as keys. 26 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Template Union Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Template Union Types 3 | sidebar: 4 | order: 41 5 | label: 41. Template Union Types 6 | --- 7 | 8 | Template union types can be used to merge and manipulate text inside the type system for instance: 9 | 10 | ```typescript 11 | type Status = 'active' | 'inactive'; 12 | type Products = 'p1' | 'p2'; 13 | type ProductId = `id-${Products}-${Status}`; // "id-p1-active" | "id-p1-inactive" | "id-p2-active" | "id-p2-inactive" 14 | ``` 15 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/The Concise TypeScript Book.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: The Concise TypeScript Book 3 | sidebar: 4 | order: 1 5 | label: 1. The Concise TypeScript Book 6 | --- 7 | 8 | The Concise TypeScript Book provides a comprehensive and succinct overview of TypeScript's capabilities. It offers clear explanations covering all aspects found in the latest version of the language, from its powerful type system to advanced features. Whether you're a beginner or an experienced developer, this book is an invaluable resource to enhance your understanding and proficiency in TypeScript. 9 | 10 | This book is completely Free and Open Source. 11 | 12 | If you found this TypeScript book valuable and wish to contribute, consider supporting my efforts via PayPal. Thanks! 13 | 14 | [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/donate/?business=QW82ZS956XLFY\&no_recurring=0\¤cy_code=EUR) 15 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/The never Type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: The never Type 3 | sidebar: 4 | order: 23 5 | label: 23. The never Type 6 | --- 7 | 8 | When a variable is narrowed to a type that cannot contain any values, the TypeScript compiler will infer that the variable must be of the `never` type. This is because The never Type represents a value that can never be produced. 9 | 10 | ```typescript 11 | const printValue = (val: string | number) => { 12 | if (typeof val === 'string') { 13 | console.log(val.toUpperCase()); 14 | } else if (typeof val === 'number') { 15 | console.log(val.toFixed(2)); 16 | } else { 17 | // val has type never here because it can never be anything other than a string or a number 18 | const neverVal: never = val; 19 | console.log(`Unexpected value: ${neverVal}`); 20 | } 21 | }; 22 | ``` 23 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Triple-Slash Directives.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Triple-Slash Directives 3 | sidebar: 4 | order: 57 5 | label: 57. Triple-Slash Directives 6 | --- 7 | 8 | Triple-slash directives are special comments that provide instructions to the compiler about how to process a file. These directives begin with three consecutive slashes (`///`) and are typically placed at the top of a TypeScript file and have no effects on the runtime behavior. 9 | 10 | Triple-slash directives are used to reference external dependencies, specify module loading behavior, enable/disable certain compiler features, and more. Few examples: 11 | 12 | Referencing a declaration file: 13 | 14 | 15 | 16 | ```typescript 17 | /// 18 | ``` 19 | 20 | Indicate the module format: 21 | 22 | 23 | 24 | ```typescript 25 | /// 26 | ``` 27 | 28 | Enable compiler options, in the following example strict mode: 29 | 30 | 31 | 32 | ```typescript 33 | /// 34 | ``` 35 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Tuple Type (Anonymous).md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Tuple Type (Anonymous) 3 | sidebar: 4 | order: 26 5 | label: 26. Tuple Type (Anonymous) 6 | --- 7 | 8 | A Tuple Type is a type that represents an array with a fixed number of elements and their corresponding types. A tuple type enforces a specific number of elements and their respective types in a fixed order. Tuple types are useful when you want to represent a collection of values with specific types, where the position of each element in the array has a specific meaning. 9 | 10 | ```typescript 11 | type Point = [number, number]; 12 | ``` 13 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Type Annotations.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Type Annotations 3 | sidebar: 4 | order: 9 5 | label: 9. Type Annotations 6 | --- 7 | 8 | On variables declared using `var`, `let` and `const`, it is possible to optionally add a type: 9 | 10 | ```typescript 11 | const x: number = 1; 12 | ``` 13 | 14 | TypeScript does a good job of inferring types, especially when simple one, so these declarations in most cases are not necessary. 15 | 16 | On functions is possible to add type annotations to parameters: 17 | 18 | ```typescript 19 | function sum(a: number, b: number) { 20 | return a + b; 21 | } 22 | ``` 23 | 24 | The following is an example using a anonymous functions (so called lambda function): 25 | 26 | ```typescript 27 | const sum = (a: number, b: number) => a + b; 28 | ``` 29 | 30 | These annotation can be avoided when a default value for a parameter is present: 31 | 32 | ```typescript 33 | const sum = (a = 10, b: number) => a + b; 34 | ``` 35 | 36 | Return type annotations can be added to functions: 37 | 38 | ```typescript 39 | const sum = (a = 10, b: number): number => a + b; 40 | ``` 41 | 42 | This is useful especially for more complex functions as writing expliciting the return type before an implementation can help better think about the function. 43 | 44 | Generally consider annotating type signatures but not the body local variables and add types always to object literals. 45 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Type Indexing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Type Indexing 3 | sidebar: 4 | order: 31 5 | label: 31. Type Indexing 6 | --- 7 | 8 | Type indexing refers to the ability to define types that can be indexed by a key that is not known in advance, using an index signature to specify the type for properties that are not explicitly declared. 9 | 10 | ```typescript 11 | type Dictionary = { 12 | [key: string]: T; 13 | }; 14 | const myDict: Dictionary = { a: 'a', b: 'b' }; 15 | console.log(myDict['a']); // Returns a 16 | ``` 17 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Type Predicates.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Type Predicates 3 | sidebar: 4 | order: 21 5 | label: 21. Type Predicates 6 | --- 7 | 8 | Type Predicates in TypeScript are functions that return a boolean value and are used to narrow the type of a variable to a more specific type. 9 | 10 | ```typescript 11 | const isString = (value: unknown): value is string => typeof value === 'string'; 12 | 13 | const foo = (bar: unknown) => { 14 | if (isString(bar)) { 15 | console.log(bar.toUpperCase()); 16 | } else { 17 | console.log('not a string'); 18 | } 19 | }; 20 | ``` 21 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Type from Func Return.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Type from Func Return 3 | sidebar: 4 | order: 33 5 | label: 33. Type from Func Return 6 | --- 7 | 8 | Type from Func Return refers to the ability to automatically infer the return type of a function based on its implementation. This allows TypeScript to determine the type of the value returned by the function without explicit type annotations. 9 | 10 | ```typescript 11 | const add = (x: number, y: number) => x + y; // TypeScript can infer that the return type of the function is a number 12 | ``` 13 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Type from Module.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Type from Module 3 | sidebar: 4 | order: 34 5 | label: 34. Type from Module 6 | --- 7 | 8 | Type from Module refers to the ability to use a module's exported values to automatically infer their types. When a module exports a value with a specific type, TypeScript can use that information to automatically infer the type of that value when it is imported into another module. 9 | 10 | 11 | 12 | ```typescript 13 | // calc.ts 14 | export const add = (x: number, y: number) => x + y; 15 | // index.ts 16 | import { add } from 'calc'; 17 | const r = add(1, 2); // r is number 18 | ``` 19 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Type from Value.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Type from Value 3 | sidebar: 4 | order: 32 5 | label: 32. Type from Value 6 | --- 7 | 8 | Type from Value in TypeScript refers to the automatic inference of a type from a value or expression through type inference. 9 | 10 | ```typescript 11 | const x = 'x'; // TypeScript can automatically infer that the type of the message variable is string 12 | ``` 13 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Union Type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Union Type 3 | sidebar: 4 | order: 29 5 | label: 29. Union Type 6 | --- 7 | 8 | A Union Type is a type that represents a value that can be one of several types. Union Types are denoted using the `|` symbol between each possible type. 9 | 10 | ```typescript 11 | let x: string | number; 12 | x = 'hello'; // Valid 13 | x = 123; // Valid 14 | ``` 15 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Unknown type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Unknown type 3 | sidebar: 4 | order: 43 5 | label: 43. Unknown type 6 | --- 7 | 8 | In TypeScript, the `unknown` type represents a value that is of an unknown type. Unlike `any` type, which allows for any type of value, `unknown` requires a type check or assertion before it can be used in a specific way so no operations are permitted on an `unknown` without first asserting or narrowing to a more specific type. 9 | 10 | The `unknown` type is only assignable to any type and the `unknown` type itself, it is a type-safe alternative to `any`. 11 | 12 | 13 | 14 | ```typescript 15 | let value: unknown; 16 | 17 | let value1: unknown = value; // Valid 18 | let value2: any = value; // Valid 19 | let value3: boolean = value; // Invalid 20 | let value4: number = value; // Invalid 21 | ``` 22 | 23 | ```typescript 24 | const add = (a: unknown, b: unknown): number | undefined => 25 | typeof a === 'number' && typeof b === 'number' ? a + b : undefined; 26 | console.log(add(1, 2)); // 3 27 | console.log(add('x', 2)); // undefined 28 | ``` 29 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/Void type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Void type 3 | sidebar: 4 | order: 44 5 | label: 44. Void type 6 | --- 7 | 8 | The `void` type is used to indicate that a function does not return a value. 9 | 10 | ```typescript 11 | const sayHello = (): void => { 12 | console.log('Hello!'); 13 | }; 14 | ``` 15 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/infer Type Inference in Conditional Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: infer Type Inference in Conditional Types 3 | sidebar: 4 | order: 39 5 | label: 39. infer Type Inference in Conditional Types 6 | --- 7 | 8 | The `infer`keyword is used in conditional types to infer (extract) the type of a generic parameter from a type that depends on it. This allows you to write more flexible and reusable type definitions. 9 | 10 | ```typescript 11 | type ElementType = T extends (infer U)[] ? U : never; 12 | type Numbers = ElementType; // number 13 | type Strings = ElementType; // string 14 | ``` 15 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/books/strictNullChecks.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: strictNullChecks 3 | sidebar: 4 | order: 16 5 | label: 16. strictNullChecks 6 | --- 7 | 8 | `strictNullChecks` is a TypeScript compiler option that enforces strict null checking. When this option is enabled, variables and parameters can only be assigned `null` or `undefined` if they have been explicitly declared to be of that type using the union type `null` | `undefined`. If a variable or parameter is not explicitly declared as nullable, TypeScript will generate an error to prevent potential runtime errors. 9 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Typescript Book 3 | description: The Concise TypeScript Book 4 | template: splash 5 | hero: 6 | tagline: The Concise TypeScript Book provides a comprehensive and succinct overview of TypeScript's capabilities. It offers clear explanations covering all aspects found in the latest version of the language, from its powerful type system to advanced features. Whether you're a beginner or an experienced developer, this book is an invaluable resource to enhance your understanding and proficiency in TypeScript.

This book is completely Free and Open Source. 7 | actions: 8 | - text: Reading now! 9 | link: /books/the-concise-typescript-book/ 10 | icon: right-arrow 11 | variant: primary 12 | --- 13 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/About the Author.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 关于作者 3 | sidebar: 4 | order: 4 5 | label: 4. 关于作者 6 | --- 7 | 8 | Simone Poggiali 是一位经验丰富的高级前端开发人员,自 90 年代以来就热衷于编写专业级代码。在他的国际职业生涯中,他为从初创公司到大型组织的广泛客户提供了众多项目。HelloFresh、Siemens、O2 和 Leroy Merlin 等著名公司都受益于他的专业知识和奉献精神。 9 | 10 | 您可以通过以下平台联系 Simone Poggiali: 11 | 12 | * 领英: 13 | * GitHub: 14 | * X.com: 15 | * 电子邮箱: gibbok.coding📧gmail.com 16 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Any type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 任意类型 3 | sidebar: 4 | order: 42 5 | label: 42. 任意类型 6 | --- 7 | 8 | `any` 类型是一种特殊类型(通用超类型),可用于表示任何类型的值(基元、对象、数组、函数、错误、符号)。它通常用于编译时未知值类型的情况,或者使用来自没有 TypeScript 类型的外部 API 或库的值时。 9 | 10 | 通过使用任何类型,您向 TypeScript 编译器指示值应该不受任何限制地表示。为了最大限度地提高代码中的类型安全性,请考虑以下事项: 11 | 12 | * 将 `any` 的使用限制在类型确实未知的特定情况下。 13 | * 不要从函数返回 `any` 类型,因为使用该函数会在代码中失去类型安全性,从而削弱类型安全性。 14 | * 如果您需要使编译器保持沉默,请使用 `@ts-ignore` 而不是 `any`。 15 | 16 | ```typescript 17 | let value: any; 18 | value = true; // 有效 19 | value = 7; // 有效 20 | ``` 21 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Assignments.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 赋值 3 | sidebar: 4 | order: 19 5 | label: 19. 赋值 6 | --- 7 | 8 | 使用赋值缩小 TypeScript 是一种根据分配给变量的值来缩小变量类型的方法。当为变量分配值时,TypeScript 会根据分配的值推断其类型,并缩小变量的类型以匹配推断的类型。 9 | 10 | ```typescript 11 | let value: string | number; 12 | value = 'hello'; 13 | if (typeof value === 'string') { 14 | console.log(value.toUpperCase()); 15 | } 16 | value = 42; 17 | if (typeof value === 'number') { 18 | console.log(value.toFixed(2)); 19 | } 20 | ``` 21 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Built-in Type Primitives.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 内置原始数据类型 3 | sidebar: 4 | order: 47 5 | label: 47. 内置原始数据类型 6 | --- 7 | 8 | TypeScript 有几个内置的原属数据类型,可用于定义变量、函数参数和返回类型: 9 | 10 | `number`: 表示数值,包括整数和浮点数。 11 | `string`: 代表文本数据。 12 | `boolean`: 代表逻辑值,可以是 true 或 false。 13 | `null`: 表示没有值。 14 | `undefined`: 表示尚未赋值或未定义的值。 15 | `symbol`: 代表唯一标识符。符号通常用作对象属性的键。 16 | `bigint`: 表示任意精度整数。 17 | `any`: 代表动态或未知类型。any 类型的变量可以保存任何类型的值,并且它们绕过类型检查。 18 | `void`: 表示不存在任何类型。它通常用作不返回值的函数的返回类型。 19 | `never`: 表示从未出现过的值的类型。它通常用作引发错误或进入无限循环的函数的返回类型。 20 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Common Built-in JS Objects.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 常见的内置JS对象 3 | sidebar: 4 | order: 48 5 | label: 48. 常见的内置JS对象 6 | --- 7 | 8 | TypeScript 是 JavaScript 的超集,它包含所有常用的内置 JavaScript 对象。您可以在 Mozilla 开发者网络 (MDN) 文档网站上找到这些对象的详细列表: 9 | 10 | 11 | 以下是一些常用的内置 JavaScript 对象的列表: 12 | 13 | * Function 14 | * Object 15 | * Boolean 16 | * Error 17 | * Number 18 | * BigInt 19 | * Math 20 | * Date 21 | * String 22 | * RegExp 23 | * Array 24 | * Map 25 | * Set 26 | * Promise 27 | * Intl 28 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Conditional Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 条件类型 3 | sidebar: 4 | order: 37 5 | label: 37. 条件类型 6 | --- 7 | 8 | 条件类型是一种创建依赖于条件的类型的方法,其中要创建的类型是根据条件的结果确定的。它们是使用 `extends` 关键字和三元运算符来定义的,以便有条件地在两种类型之间进行选择。 9 | 10 | ```typescript 11 | type IsArray = T extends any[] ? true : false; 12 | 13 | const myArray = [1, 2, 3]; 14 | const myNumber = 42; 15 | 16 | type IsMyArrayAnArray = IsArray; // true 类型 17 | type IsMyNumberAnArray = IsArray; // false 类型 18 | ``` 19 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Control Flow Analysis.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 控制流分析 3 | sidebar: 4 | order: 20 5 | label: 20. 控制流分析 6 | --- 7 | 8 | TypeScript 中的控制流分析是一种静态分析代码流以推断变量类型的方法,允许编译器根据分析结果根据需要缩小这些变量的类型。 9 | 10 | 在 TypeScript 4.4 之前,代码流分析仅适用于 if 语句中的代码,但从 TypeScript 4.4 开始,它还可以应用于条件表达式和通过 const 变量间接引用的判别式属性访问。 11 | 12 | 例如: 13 | 14 | ```typescript 15 | const f1 = (x: unknown) => { 16 | const isString = typeof x === 'string'; 17 | if (isString) { 18 | x.length; 19 | } 20 | }; 21 | 22 | const f2 = ( 23 | obj: { kind: 'foo'; foo: string } | { kind: 'bar'; bar: number } 24 | ) => { 25 | const isFoo = obj.kind === 'foo'; 26 | if (isFoo) { 27 | obj.foo; 28 | } else { 29 | obj.bar; 30 | } 31 | }; 32 | ``` 33 | 34 | 一些未发生缩小的示例: 35 | 36 | 37 | 38 | ```typescript 39 | const f1 = (x: unknown) => { 40 | let isString = typeof x === 'string'; 41 | if (isString) { 42 | x.length; // 错误, 没有缩小,因为 isString 不是常量 43 | } 44 | }; 45 | 46 | const f6 = ( 47 | obj: { kind: 'foo'; foo: string } | { kind: 'bar'; bar: number } 48 | ) => { 49 | const isFoo = obj.kind === 'foo'; 50 | obj = obj; 51 | if (isFoo) { 52 | obj.foo; // 错误, 没有缩小,因为 obj 在函数体中被赋值 53 | } 54 | }; 55 | ``` 56 | 57 | 注意: 在条件表达式中最多分析五个间接级别。 58 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Differences between Type and Interface.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 类型和接口之间的差异 3 | sidebar: 4 | order: 51 5 | label: 51. 类型和接口之间的差异 6 | --- 7 | 8 | 声明合并(增强): 9 | 10 | 接口支持声明合并,这意味着您可以定义多个具有相同名称的接口,TypeScript 会将它们合并为具有组合属性和方法的单个接口。 另一方面,类型不支持声明合并。 当您想要添加额外的功能或自定义现有类型而不修改原始定义或修补丢失或不正确的类型时,这可能会很有帮助。 11 | 12 | ```typescript 13 | interface A { 14 | x: string; 15 | } 16 | interface A { 17 | y: string; 18 | } 19 | const j: A = { 20 | x: 'xx', 21 | y: 'yy', 22 | }; 23 | ``` 24 | 25 | 扩展其他类型/接口: 26 | 27 | 类型和接口都可以扩展其他类型/接口,但语法不同。 对于接口,您可以使用“extends”关键字从其他接口继承属性和方法。 但是,接口无法扩展像联合类型这样的复杂类型。 28 | 29 | ```typescript 30 | interface A { 31 | x: string; 32 | y: number; 33 | } 34 | interface B extends A { 35 | z: string; 36 | } 37 | const car: B = { 38 | x: 'x', 39 | y: 123, 40 | z: 'z', 41 | }; 42 | ``` 43 | 44 | 对于类型,您可以使用 & 运算符将多个类型合并为单个类型(交集)。 45 | 46 | ```typescript 47 | interface A { 48 | x: string; 49 | y: number; 50 | } 51 | 52 | type B = A & { 53 | j: string; 54 | }; 55 | 56 | const c: B = { 57 | x: 'x', 58 | y: 123, 59 | j: 'j', 60 | }; 61 | ``` 62 | 63 | 并集和交集类型: 64 | 65 | 在定义并集和交集类型时,类型更加灵活。 通过“type”关键字,您可以使用“|”运算符轻松创建联合类型,并使用“&”运算符创建交集类型。 虽然接口也可以间接表示联合类型,但它们没有对交集类型的内置支持。 66 | 67 | ```typescript 68 | type Department = 'dep-x' | 'dep-y'; // 并集 69 | 70 | type Person = { 71 | name: string; 72 | age: number; 73 | }; 74 | 75 | type Employee = { 76 | id: number; 77 | department: Department; 78 | }; 79 | 80 | type EmployeeInfo = Person & Employee; // 交集 81 | ``` 82 | 83 | 接口示例: 84 | 85 | ```typescript 86 | interface A { 87 | x: 'x'; 88 | } 89 | interface B { 90 | y: 'y'; 91 | } 92 | 93 | type C = A | B; // 接口的并集 94 | ``` 95 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Discriminated Unions.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 可区分联合 3 | sidebar: 4 | order: 22 5 | label: 22. 可区分联合 6 | --- 7 | 8 | TypeScript 中的可区分联合是一种联合类型,它使用称为判别式的公共属性来缩小联合的可能类型集。 9 | 10 | ```typescript 11 | type Square = { 12 | kind: 'square'; // 判别式 13 | size: number; 14 | }; 15 | 16 | type Circle = { 17 | kind: 'circle'; // 判别式 18 | radius: number; 19 | }; 20 | 21 | type Shape = Square | Circle; 22 | 23 | const area = (shape: Shape) => { 24 | switch (shape.kind) { 25 | case 'square': 26 | return Math.pow(shape.size, 2); 27 | case 'circle': 28 | return Math.PI * Math.pow(shape.radius, 2); 29 | } 30 | }; 31 | 32 | const square: Square = { kind: 'square', size: 5 }; 33 | const circle: Circle = { kind: 'circle', radius: 2 }; 34 | 35 | console.log(area(square)); // 25 36 | console.log(area(circle)); // 12.566370614359172 37 | ``` 38 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Distributive Conditional Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 分配条件类型 3 | sidebar: 4 | order: 38 5 | label: 38. 分配条件类型 6 | --- 7 | 8 | 分布式条件类型是一种功能,通过单独对联合的每个成员应用转换,允许类型分布在类型的联合上。当使用映射类型或高阶类型时,这尤其有用。 9 | 10 | ```typescript 11 | type Nullable = T extends any ? T | null : never; 12 | type NumberOrBool = number | boolean; 13 | type NullableNumberOrBool = Nullable; // number | boolean | null 14 | ``` 15 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Erased Structural Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 擦除的结构类型 3 | sidebar: 4 | order: 54 5 | label: 54. 擦除的结构类型 6 | --- 7 | 8 | 在 TypeScript 中,对象不必匹配特定的、精确的类型。例如,如果我们创建一个满足接口要求的对象,我们就可以在需要该接口的地方使用该对象,即使它们之间没有显式连接。例子: 9 | 10 | ```typescript 11 | type NameProp1 = { 12 | prop1: string; 13 | }; 14 | 15 | function log(x: NameProp1) { 16 | console.log(x.prop1); 17 | } 18 | 19 | const obj = { 20 | prop2: 123, 21 | prop1: 'Origin', 22 | }; 23 | 24 | log(obj); // 有效 25 | ``` 26 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Exhaustiveness checking.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 详尽性检查 3 | sidebar: 4 | order: 24 5 | label: 24. 详尽性检查 6 | --- 7 | 8 | 详尽性检查是 TypeScript 中的一项功能,可确保在 `switch` 语句或 `if` 语句中处理可区分联合的所有可能情况。 9 | 10 | ```typescript 11 | type Direction = 'up' | 'down'; 12 | 13 | const move = (direction: Direction) => { 14 | switch (direction) { 15 | case 'up': 16 | console.log('Moving up'); 17 | break; 18 | case 'down': 19 | console.log('Moving down'); 20 | break; 21 | default: 22 | const exhaustiveCheck: never = direction; 23 | console.log(exhaustiveCheck); // 这行永远不会被执行 24 | } 25 | }; 26 | ``` 27 | 28 | 该 `never` 类型用于确保默认情况是详尽的,并且如果将新值添加到 Direction 类型而未在 switch 语句中进行处理,则 TypeScript 将引发错误。 29 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Extending Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 扩展类型 3 | sidebar: 4 | order: 13 5 | label: 13. 扩展类型 6 | --- 7 | 8 | 可以扩展 `interface`(从另一种类型复制成员): 9 | 10 | ```typescript 11 | interface X { 12 | a: string; 13 | } 14 | interface Y extends X { 15 | b: string; 16 | } 17 | ``` 18 | 19 | 还可以从多种 `interface` 进行扩展: 20 | 21 | ```typescript 22 | interface A { 23 | a: string; 24 | } 25 | interface B { 26 | b: string; 27 | } 28 | interface Y extends A, B { 29 | y: string; 30 | } 31 | ``` 32 | 33 | 该 `extends` 关键字仅适用于 `interface`,因为 `type` 使用交集: 34 | 35 | ```typescript 36 | type A = { 37 | a: number; 38 | }; 39 | type B = { 40 | b: number; 41 | }; 42 | type C = A & B; 43 | ``` 44 | 45 | 可以使用 `interface` 来扩展类 `type`,但反之则不然: 46 | 47 | ```typescript 48 | type A = { 49 | a: string; 50 | }; 51 | interface B extends A { 52 | b: string; 53 | } 54 | ``` 55 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Fixed Length Tuple.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 固定长度元组 3 | sidebar: 4 | order: 28 5 | label: 28. 固定长度元组 6 | --- 7 | 8 | 固定长度元组是一种特定类型的元组,它强制执行特定类型的固定数量的元素,并且一旦定义元组就不允许对其长度进行任何修改。 9 | 10 | 当您需要表示具有特定数量的元素和特定类型的值的集合,并且您希望确保元组的长度和类型不会无意中更改时,固定长度元组非常有用。 11 | 12 | 13 | 14 | ```typescript 15 | const x = [10, 'hello'] as const; 16 | x.push(2); // 错误 17 | ``` 18 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Generics.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 泛型 3 | sidebar: 4 | order: 53 5 | label: 53. 泛型 6 | --- 7 | 8 | 泛型允许您创建可与多种类型一起使用的可重用组件和函数。使用泛型,您可以参数化类型、函数和接口,从而允许它们对不同类型进行操作,而无需事先显式指定它们。 9 | 10 | 泛型允许您使代码更加灵活和可重用。 11 | 12 | ### 泛型类型 13 | 14 | 要定义泛型类型,可以使用尖括号 (`<>`) 来指定类型参数,例如: 15 | 16 | ```typescript 17 | function identity(arg: T): T { 18 | return arg; 19 | } 20 | const a = identity('x'); 21 | const b = identity(123); 22 | 23 | const getLen = (data: ReadonlyArray) => data.length; 24 | const len = getLen([1, 2, 3]); 25 | ``` 26 | 27 | ### 泛型类 28 | 29 | 泛型也可以应用于类,这样它们就可以通过使用类型参数来处理多种类型。这对于创建可重用的类定义非常有用,这些定义可以在保持类型安全的同时对不同的数据类型进行操作。 30 | 31 | ```typescript 32 | class Container { 33 | private item: T; 34 | 35 | constructor(item: T) { 36 | this.item = item; 37 | } 38 | 39 | getItem(): T { 40 | return this.item; 41 | } 42 | } 43 | 44 | const numberContainer = new Container(123); 45 | console.log(numberContainer.getItem()); // 123 46 | 47 | const stringContainer = new Container('hello'); 48 | console.log(stringContainer.getItem()); // hello 49 | ``` 50 | 51 | ### 泛型约束 52 | 53 | 可以使用关键字 `extends` 后跟类型参数必须满足的类型或接口来约束泛型参数。 54 | 55 | 在下面的示例中,T 必须正确包含 `length` 才能有效: 56 | 57 | 58 | 59 | ```typescript 60 | const printLen = (value: T): void => { 61 | console.log(value.length); 62 | }; 63 | 64 | printLen('Hello'); // 5 65 | printLen([1, 2, 3]); // 3 66 | printLen({ length: 10 }); // 10 67 | printLen(123); // 无效 68 | ``` 69 | 70 | 3.4 RC 版中引入的泛型的一个有趣功能是高阶函数类型推断,它引入了传播泛型类型参数: 71 | 72 | ```typescript 73 | declare function pipe( 74 | ab: (...args: A) => B, 75 | bc: (b: B) => C 76 | ): (...args: A) => C; 77 | 78 | declare function list(a: T): T[]; 79 | declare function box(x: V): { value: V }; 80 | 81 | const listBox = pipe(list, box); // (a: T) => { value: T[] } 82 | const boxList = pipe(box, list); // (x: V) => { value: V }[] 83 | ``` 84 | 85 | 此功能允许更轻松地键入安全的无点风格编程,这在函数式编程中很常见。 86 | 87 | ### 泛型上下文缩小 88 | 89 | 泛型上下文缩小是 TypeScript 中的机制,允许编译器根据使用泛型参数的上下文来缩小泛型参数的类型,在条件语句中使用泛型类型时非常有用: 90 | 91 | ```typescript 92 | function process(value: T): void { 93 | if (typeof value === 'string') { 94 | // Value 的类型被缩小到 'string' 类型 95 | console.log(value.length); 96 | } else if (typeof value === 'number') { 97 | // Value 的类型被缩小到 'number' 类型 98 | console.log(value.toFixed(2)); 99 | } 100 | } 101 | 102 | process('hello'); // 5 103 | process(3.14159); // 3.14 104 | ``` 105 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Index Signatures.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 索引签名 3 | sidebar: 4 | order: 12 5 | label: 12. 索引签名 6 | --- 7 | 8 | 在 TypeScript 中,我们可以使用 `string` 、`number` 和 `symbol` 作为索引签名: 9 | 10 | ```typescript 11 | type K = { 12 | [name: string | number]: string; 13 | }; 14 | const k: K = { x: 'x', 1: 'b' }; 15 | console.log(k['x']); 16 | console.log(k[1]); 17 | console.log(k['1']); // 同 k[1] 的结果相同 18 | ``` 19 | 20 | 请注意,JavaScript 会自动将 `number` 的索引转换相同值的 'string'索引, 比如 `k[1]` 和 `k["1"]` 返回相同值。 21 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Interface and Type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 接口及类型 3 | sidebar: 4 | order: 46 5 | label: 46. 接口及类型 6 | --- 7 | 8 | ### 通用语法 9 | 10 | 在 TypeScript 中,接口定义对象的结构,指定对象必须具有的属性或方法的名称和类型。在 TypeScript 中定义接口的常用语法如下: 11 | 12 | 13 | 14 | ```typescript 15 | interface InterfaceName { 16 | property1: Type1; 17 | // ... 18 | method1(arg1: ArgType1, arg2: ArgType2): ReturnType; 19 | // ... 20 | } 21 | ``` 22 | 23 | 类型定义也类似: 24 | 25 | 26 | 27 | ```typescript 28 | type TypeName = { 29 | property1: Type1; 30 | // ... 31 | method1(arg1: ArgType1, arg2: ArgType2): ReturnType; 32 | // ... 33 | }; 34 | ``` 35 | 36 | `interface InterfaceName` 或者 `type TypeName`: 定义接口的名称。 37 | `property1`: `Type1`: 指定接口的属性及其相应的类型。可以定义多个属性,每个属性用分号分隔。 38 | `method1(arg1: ArgType1, arg2: ArgType2): ReturnType;`: 指定接口的方法。方法用其名称进行定义,后跟括号中的参数列表和返回类型。可以定义多个方法,每个方法用分号分隔。 39 | 40 | 接口示例: 41 | 42 | ```typescript 43 | interface Person { 44 | name: string; 45 | age: number; 46 | greet(): void; 47 | } 48 | ``` 49 | 50 | 类型示例: 51 | 52 | ```typescript 53 | type TypeName = { 54 | property1: string; 55 | method1(arg1: string, arg2: string): string; 56 | }; 57 | ``` 58 | 59 | 在 TypeScript 中,类型用于定义数据的形状并强制执行类型检查。在 TypeScript 中定义类型有几种常见的语法,具体取决于具体的用例。这里有些例子: 60 | 61 | ### 基本类型 62 | 63 | ```typescript 64 | let myNumber: number = 123; // 数字类型 65 | let myBoolean: boolean = true; // 布尔类型 66 | let myArray: string[] = ['a', 'b']; // 字符串数组 67 | let myTuple: [string, number] = ['a', 123]; // 元组 68 | ``` 69 | 70 | ### 对象和接口 71 | 72 | ```typescript 73 | const x: { name: string; age: number } = { name: 'Simon', age: 7 }; 74 | ``` 75 | 76 | ### 并集和交集类型 77 | 78 | ```typescript 79 | type MyType = string | number; // 并集 80 | let myUnion: MyType = 'hello'; // 可以是字符串 81 | myUnion = 123; // 或者是一个数字 82 | 83 | type TypeA = { name: string }; 84 | type TypeB = { age: number }; 85 | type CombinedType = TypeA & TypeB; // 交集 86 | let myCombined: CombinedType = { name: 'John', age: 25 }; // 对象同时有name和age属性 87 | ``` 88 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Intersection Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 交集类型 3 | sidebar: 4 | order: 30 5 | label: 30. 交集类型 6 | --- 7 | 8 | 交集类型是表示具有两种或多种类型的所有属性的值的类型。交叉类型在每种类型之间使用 & 符号表示。 9 | 10 | ```typescript 11 | type X = { 12 | a: string; 13 | }; 14 | 15 | type Y = { 16 | b: string; 17 | }; 18 | 19 | type J = X & Y; // 交集 20 | 21 | const j: J = { 22 | a: 'a', 23 | b: 'b', 24 | }; 25 | ``` 26 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 介绍 3 | sidebar: 4 | order: 3 5 | label: 3. 介绍 6 | --- 7 | 8 | 欢迎来到简洁的TypeScript之书!本指南为您提供有效 TypeScript 开发的基本知识和实践技能。发现编写干净、健壮的代码的关键概念和技术。无论您是初学者还是经验丰富的开发人员,本书都可以作为在项目中利用 TypeScript 强大功能的综合指南和便捷参考。 9 | 10 | 本书涵盖了 TypeScript 5.2。 11 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Literal Inference.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 字面量推断 3 | sidebar: 4 | order: 15 5 | label: 15. 字面量推断 6 | --- 7 | 8 | 字面量推断是 TypeScript 中的一项功能,允许根据变量或参数的值推断其类型。 9 | 10 | 在下面的示例中,我们可以看到 TypeScript 认为x文字类型是因为该值以后不能随时更改,而y被推断为字符串,因为它以后可以随时修改。 11 | 12 | ```typescript 13 | const x = 'x'; // x 为字面量类型, 因为值不能改变 14 | let y = 'y'; // string, 我们能改变这个值 15 | ``` 16 | 17 | 在下面的示例中,我们可以看到 `o.x` 被推断为 `string`(而不是字面量的a),因为 TypeScript 认为该值可以在以后随时更改。 18 | 19 | 20 | 21 | ```typescript 22 | type X = 'a' | 'b'; 23 | 24 | let o = { 25 | x: 'a', // 这是一个更宽的 string 26 | }; 27 | 28 | const fn = (x: X) => `${x}-foo`; 29 | 30 | console.log(fn(o.x)); // 'string' 类型的参数不能赋值给 'X' 类型的参数 31 | ``` 32 | 33 | 正如你所看到的代码在传递 `o.x` 给 `fn` 作为一个狭窄类型时,抛出了一个错误。 34 | 35 | 我们能通过使用 `const` 或者 `X` 来借助类型推断解决这个问题: 36 | 37 | 38 | 39 | ```typescript 40 | let o = { 41 | x: 'a' as const, 42 | }; 43 | ``` 44 | 45 | or: 46 | 47 | 48 | 49 | ```typescript 50 | let o = { 51 | x: 'a' as X, 52 | }; 53 | ``` 54 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Literal Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 字面量类型 3 | sidebar: 4 | order: 14 5 | label: 14. 字面量类型 6 | --- 7 | 8 | 文字类型是来自集体类型的单个元素集,它定义了一个非常精确的值,即 JavaScript 原始数据。 9 | 10 | TypeScript 中的文字类型是数字、字符串和布尔值。 11 | 12 | 示例如下: 13 | 14 | ```typescript 15 | const a = 'a'; // 字符串字面量类型 16 | const b = 1; // 数字字面量类型 17 | const c = true; // 布尔字面量类型 18 | ``` 19 | 20 | 字符串、数字和布尔字面量类型用于联合、类型保护和类型别名。在下面的示例中,您可以看到类型别名联合,O可以是指定的唯一值,而不是任何其他字符串: 21 | 22 | ```typescript 23 | type O = 'a' | 'b' | 'c'; 24 | ``` 25 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Mapped Type Modifiers.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 映射类型修饰符 3 | sidebar: 4 | order: 36 5 | label: 36. 映射类型修饰符 6 | --- 7 | 8 | TypeScript 中的映射类型修饰符支持对现有类型中的属性进行转换: 9 | 10 | * `readonly` 或 `+readonly`:这会将映射类型中的属性呈现为只读。 11 | * `-readonly`:这允许映射类型中的属性是可变的。 12 | * `?`:这将映射类型中的属性指定为可选。 13 | 14 | 例子: 15 | 16 | ```typescript 17 | type ReadOnly = { readonly [P in keyof T]: T[P] }; // 所有属性标记为只读 18 | 19 | type Mutable = { -readonly [P in keyof T]: T[P] }; // 所有标记为可变的属性 20 | 21 | type MyPartial = { [P in keyof T]?: T[P] }; // 所有标记为可选的属性 22 | ``` 23 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Mapped Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 映射类型 3 | sidebar: 4 | order: 35 5 | label: 35. 映射类型 6 | --- 7 | 8 | TypeScript 中的映射类型允许您通过使用映射函数转换每个属性来基于现有类型创建新类型。通过映射现有类型,您可以创建以不同格式表示相同信息的新类型。要创建映射类型,您可以使用运算符访问现有类型的属性 `keyof` ,然后更改它们以生成新类型。在以下示例中: 9 | 10 | ```typescript 11 | type MyMappedType = { 12 | [P in keyof T]: T[P][]; 13 | }; 14 | type MyType = { 15 | foo: string; 16 | bar: number; 17 | }; 18 | type MyNewType = MyMappedType; 19 | const x: MyNewType = { 20 | foo: ['hello', 'world'], 21 | bar: [1, 2, 3], 22 | }; 23 | ``` 24 | 25 | 我们定义 MyMappedType 来映射 T 的属性,创建一个新类型,其中每个属性都是其原始类型的数组。使用它,我们创建 MyNewType 来表示与 MyType 相同的信息,但每个属性都是一个数组。 26 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Merging and Extension.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 合并与扩展 3 | sidebar: 4 | order: 50 5 | label: 50. 合并与扩展 6 | --- 7 | 8 | 合并和扩展是指与使用类型和接口相关的两个不同概念。 9 | 10 | 合并允许您将多个同名声明合并到一个定义中,例如,当您多次定义同名接口时: 11 | 12 | ```typescript 13 | interface X { 14 | a: string; 15 | } 16 | 17 | interface X { 18 | b: number; 19 | } 20 | 21 | const person: X = { 22 | a: 'a', 23 | b: 7, 24 | }; 25 | ``` 26 | 27 | 扩展是指扩展或继承现有类型或接口以创建新类型或接口的能力。它是一种向现有类型添加附加属性或方法而不修改其原始定义的机制。例子: 28 | 29 | ```typescript 30 | interface Animal { 31 | name: string; 32 | eat(): void; 33 | } 34 | 35 | interface Bird extends Animal { 36 | sing(): void; 37 | } 38 | 39 | const dog: Bird = { 40 | name: 'Bird 1', 41 | eat() { 42 | console.log('Eating'); 43 | }, 44 | sing() { 45 | console.log('Singing'); 46 | }, 47 | }; 48 | ``` 49 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Named Tuple Type (Labeled).md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 命名元组类型(已标记) 3 | sidebar: 4 | order: 27 5 | label: 27. 命名元组类型(已标记) 6 | --- 7 | 8 | 元组类型可以包含每个元素的可选标签或名称。 这些标签用于提高可读性和工具帮助,不会影响您可以使用它们执行的操作。 9 | 10 | ```typescript 11 | type T = string; 12 | type Tuple1 = [T, T]; 13 | type Tuple2 = [a: T, b: T]; 14 | type Tuple3 = [a: T, T]; // 命名元组加匿名元组 15 | ``` 16 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Namespacing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 命名空间 3 | sidebar: 4 | order: 55 5 | label: 55. 命名空间 6 | --- 7 | 8 | 在 TypeScript 中,命名空间用于将代码组织到逻辑容器中,防止命名冲突并提供一种将相关代码分组在一起的方法。使用关键字 `export` 允许在"外部"模块中访问名称空间。 9 | 10 | ```typescript 11 | export namespace MyNamespace { 12 | export interface MyInterface1 { 13 | prop1: boolean; 14 | } 15 | export interface MyInterface2 { 16 | prop2: string; 17 | } 18 | } 19 | 20 | const a: MyNamespace.MyInterface1 = { 21 | prop1: true, 22 | }; 23 | ``` 24 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Narrowing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 缩小范围 3 | sidebar: 4 | order: 18 5 | label: 18. 缩小范围 6 | --- 7 | 8 | TypeScript 缩小范围是细化条件块内变量类型的过程。这在使用联合类型时很有用,其中一个变量可以有多个类型。 9 | 10 | TypeScript 可识别多种缩小类型范围的方法: 11 | 12 | ### typeof 类型保护 13 | 14 | typeof 类型保护是 TypeScript 中的一种特定类型保护,它根据变量的内置 JavaScript 类型检查变量的类型。 15 | 16 | ```typescript 17 | const fn = (x: number | string) => { 18 | if (typeof x === 'number') { 19 | return x + 1; // x 是数字 20 | } 21 | return -1; 22 | }; 23 | ``` 24 | 25 | ### 真实性缩小 26 | 27 | TypeScript 中的真实性缩小是通过检查变量是真还是假来相应地缩小其类型来实现的。 28 | 29 | ```typescript 30 | const toUpperCase = (name: string | null) => { 31 | if (name) { 32 | return name.toUpperCase(); 33 | } else { 34 | return null; 35 | } 36 | }; 37 | ``` 38 | 39 | ### 相等缩小 40 | 41 | TypeScript 中的相等缩小通过检查变量是否等于特定值来相应缩小其类型。 42 | 43 | 它与`switch`语句和等号运算符(例如`===`、`!==`、`==`和`!=`)结合使用来缩小类型范围。 44 | 45 | ```typescript 46 | const checkStatus = (status: 'success' | 'error') => { 47 | switch (status) { 48 | case 'success': 49 | return true 50 | case 'error': 51 | return null 52 | } 53 | }; 54 | ``` 55 | 56 | ### In运算符缩小 57 | 58 | TypeScript 中的 `in` 运算符缩小范围是一种根据变量类型中是否存在属性来缩小变量类型的方法。 59 | 60 | ```typescript 61 | type Dog = { 62 | name: string; 63 | breed: string; 64 | }; 65 | 66 | type Cat = { 67 | name: string; 68 | likesCream: boolean; 69 | }; 70 | 71 | const getAnimalType = (pet: Dog | Cat) => { 72 | if ('breed' in pet) { 73 | return 'dog'; 74 | } else { 75 | return 'cat'; 76 | } 77 | }; 78 | ``` 79 | 80 | ### instanceof 缩小 81 | 82 | TypeScript 中的 `instanceof` 运算符缩小是一种根据变量的构造函数缩小变量类型的方法,方法是检查对象是否是某个类或接口的实例。 83 | 84 | ```typescript 85 | class Square { 86 | constructor(public width: number) {} 87 | } 88 | class Rectangle { 89 | constructor( 90 | public width: number, 91 | public height: number 92 | ) {} 93 | } 94 | function area(shape: Square | Rectangle) { 95 | if (shape instanceof Square) { 96 | return shape.width * shape.width; 97 | } else { 98 | return shape.width * shape.height; 99 | } 100 | } 101 | const square = new Square(5); 102 | const rectangle = new Rectangle(5, 10); 103 | console.log(area(square)); // 25 104 | console.log(area(rectangle)); // 50 105 | ``` 106 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Never type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Never类型 3 | sidebar: 4 | order: 45 5 | label: 45. Never类型 6 | --- 7 | 8 | `never` 类型表示从未出现过的值。它用于表示从不返回或抛出错误的函数或表达式。 9 | 10 | 例如无限循环: 11 | 12 | ```typescript 13 | const infiniteLoop = (): never => { 14 | while (true) { 15 | // 做点什么 16 | } 17 | }; 18 | ``` 19 | 20 | 抛出错误: 21 | 22 | ```typescript 23 | const throwError = (message: string): never => { 24 | throw new Error(message); 25 | }; 26 | ``` 27 | 28 | `never` 类型对于确保类型安全和捕获代码中的潜在错误很有用。当与其他类型和控制流语句结合使用时,它可以帮助 TypeScript 分析和推断更精确的类型,例如: 29 | 30 | ```typescript 31 | type Direction = 'up' | 'down'; 32 | const move = (direction: Direction): void => { 33 | switch (direction) { 34 | case 'up': 35 | // 向上移动 36 | break; 37 | case 'down': 38 | // 向下移动 39 | break; 40 | default: 41 | const exhaustiveCheck: never = direction; 42 | throw new Error(`Unhandled direction: ${exhaustiveCheck}`); 43 | } 44 | }; 45 | ``` 46 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Object Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 对象类型 3 | sidebar: 4 | order: 25 5 | label: 25. 对象类型 6 | --- 7 | 8 | 在 TypeScript 中,对象类型描述对象的形状。它们指定对象属性的名称和类型,以及这些属性是必需的还是可选的。 9 | 10 | 在 TypeScript 中,您可以通过两种主要方式定义对象类型: 11 | 12 | 通过指定对象属性的名称、类型和可选性来定义对象的形状的接口。 13 | 14 | ```typescript 15 | interface User { 16 | name: string; 17 | age: number; 18 | email?: string; 19 | } 20 | ``` 21 | 22 | 类型别名与接口类似,定义了对象的形状。但是,它还可以基于现有类型或现有类型的组合创建新的自定义类型。这包括定义联合类型、交集类型和其他复杂类型。 23 | 24 | ```typescript 25 | type Point = { 26 | x: number; 27 | y: number; 28 | }; 29 | ``` 30 | 31 | 也可以匿名定义类型: 32 | 33 | ```typescript 34 | const sum = (x: { a: number; b: number }) => x.a + x.b; 35 | console.log(sum({ a: 5, b: 1 })); 36 | ``` 37 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Optional Properties.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 可选属性 3 | sidebar: 4 | order: 10 5 | label: 10. 可选属性 6 | --- 7 | 8 | 对象可以通过在属性名称末尾添加问号 `?` 来指定可选属性: 9 | 10 | ```typescript 11 | type X = { 12 | a: number; 13 | b?: number; // 可选的 14 | }; 15 | ``` 16 | 17 | 当属性是可选的时,可以指定默认值 18 | 19 | ```typescript 20 | type X = { 21 | a: number; 22 | b?: number; 23 | }; 24 | const x = ({ a, b = 100 }: X) => a + b; 25 | ``` 26 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Overloads.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 重载 3 | sidebar: 4 | order: 49 5 | label: 49. 重载 6 | --- 7 | 8 | TypeScript 中的函数重载允许您为单个函数名称定义多个函数签名,从而使您能够定义可以多种方式调用的函数。这是一个例子: 9 | 10 | ```typescript 11 | // 重载 12 | function sayHi(name: string): string; 13 | function sayHi(names: string[]): string[]; 14 | 15 | // 实现 16 | function sayHi(name: unknown): unknown { 17 | if (typeof name === 'string') { 18 | return `Hi, ${name}!`; 19 | } else if (Array.isArray(name)) { 20 | return name.map(name => `Hi, ${name}!`); 21 | } 22 | throw new Error('Invalid value'); 23 | } 24 | 25 | sayHi('xx'); // 有效 26 | sayHi(['aa', 'bb']); // 有效 27 | ``` 28 | 29 | 这是在 `class` 中使用函数重载的另一个示例: 30 | 31 | ```typescript 32 | class Greeter { 33 | message: string; 34 | 35 | constructor(message: string) { 36 | this.message = message; 37 | } 38 | 39 | // 重载 40 | sayHi(name: string): string; 41 | sayHi(names: string[]): ReadonlyArray; 42 | 43 | // 实现 44 | sayHi(name: unknown): unknown { 45 | if (typeof name === 'string') { 46 | return `${this.message}, ${name}!`; 47 | } else if (Array.isArray(name)) { 48 | return name.map(name => `${this.message}, ${name}!`); 49 | } 50 | throw new Error('value is invalid'); 51 | } 52 | } 53 | console.log(new Greeter('Hello').sayHi('Simon')); 54 | ``` 55 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Predefined Conditional Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 预定义条件类型 3 | sidebar: 4 | order: 40 5 | label: 40. 预定义条件类型 6 | --- 7 | 8 | 在 TypeScript 中,预定义的条件类型是语言提供的内置条件类型。它们旨在根据给定类型的特征执行常见的类型转换。 9 | 10 | `Exclude`: 此类型从 Type 中删除可分配给 ExcludedType 的所有类型。 11 | 12 | `Extract`: 此类型从 Union 中提取可分配给 Type 的所有类型。 13 | 14 | `NonNullable`: 此类型从 Type 中删除 null 和 undefined。 15 | 16 | `ReturnType`: 此类型提取函数 Type 的返回类型。 17 | 18 | `Parameters`: 该类型提取函数类型的参数类型。 19 | 20 | `Required`: 此类型使 Type 中的所有属性成为必需。 21 | 22 | `Partial`: 此类型使 Type 中的所有属性都是可选的。 23 | 24 | `Readonly`: 此类型使 Type 中的所有属性变为只读。 25 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Readonly Properties.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 只读属性 3 | sidebar: 4 | order: 11 5 | label: 11. 只读属性 6 | --- 7 | 8 | 是否可以通过使用修饰符来防止对属性进行写入,`readonly` 以确保该属性不能被重写,但不提供任何完全不变性的保证: 9 | 10 | ```typescript 11 | interface Y { 12 | readonly a: number; 13 | } 14 | 15 | type X = { 16 | readonly a: number; 17 | }; 18 | 19 | type J = Readonly<{ 20 | a: number; 21 | }>; 22 | 23 | type K = { 24 | readonly [index: number]: string; 25 | }; 26 | ``` 27 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Symbols.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Symbols 3 | sidebar: 4 | order: 56 5 | label: 56. Symbols 6 | --- 7 | 8 | 符号是一种原始数据类型,表示不可变值,保证在程序的整个生命周期中全局唯一。 9 | 10 | 符号可以用作对象属性的键,并提供一种创建不可枚举属性的方法。 11 | 12 | ```typescript 13 | const key1: symbol = Symbol('key1'); 14 | const key2: symbol = Symbol('key2'); 15 | 16 | const obj = { 17 | [key1]: 'value 1', 18 | [key2]: 'value 2', 19 | }; 20 | 21 | console.log(obj[key1]); // value 1 22 | console.log(obj[key2]); // value 2 23 | ``` 24 | 25 | 在 WeakMap 和 WeakSet 中,现在允许符号作为键。 26 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Template Union Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 模板联合类型 3 | sidebar: 4 | order: 41 5 | label: 41. 模板联合类型 6 | --- 7 | 8 | 模板联合类型可用于合并和操作类型系统内的文本,例如: 9 | 10 | ```typescript 11 | type Status = 'active' | 'inactive'; 12 | type Products = 'p1' | 'p2'; 13 | type ProductId = `id-${Products}-${Status}`; // "id-p1-active" | "id-p1-inactive" | "id-p2-active" | "id-p2-inactive" 14 | ``` 15 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/The Concise TypeScript Book.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 简洁的TypeScript之书 3 | sidebar: 4 | order: 1 5 | label: 1. 简洁的TypeScript之书 6 | --- 7 | 8 | 《Concise TypeScript Book》全面而简洁地概述了 TypeScript 的功能。它提供了清晰的解释,涵盖了该语言最新版本中的所有方面,从强大的类型系统到高级功能。无论您是初学者还是经验丰富的开发人员,本书都是增强您对 TypeScript 的理解和熟练程度的宝贵资源。 9 | 10 | 本书完全免费且开源。 11 | 12 | 如果您发现这本 TypeScript 书籍很有价值并希望做出贡献,请考虑通过 PayPal 支持我的努力。谢谢! 13 | 14 | [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/donate/?business=QW82ZS956XLFY\&no_recurring=0\¤cy_code=EUR) 15 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/The never Type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: never 类型 3 | sidebar: 4 | order: 23 5 | label: 23. never 类型 6 | --- 7 | 8 | 当变量缩小为不能包含任何值的类型时,TypeScript 编译器将推断该变量必须属于该never类型。这是因为 never 类型代表永远无法生成的值。 9 | 10 | ```typescript 11 | const printValue = (val: string | number) => { 12 | if (typeof val === 'string') { 13 | console.log(val.toUpperCase()); 14 | } else if (typeof val === 'number') { 15 | console.log(val.toFixed(2)); 16 | } else { 17 | // val 在这里的类型为 never,因为它只能是字符串或数字 18 | const neverVal: never = val; 19 | console.log(`Unexpected value: ${neverVal}`); 20 | } 21 | }; 22 | ``` 23 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Triple-Slash Directives.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 三斜杠指令 3 | sidebar: 4 | order: 57 5 | label: 57. 三斜杠指令 6 | --- 7 | 8 | 三斜杠指令是特殊注释,为编译器提供有关如何处理文件的说明。这些指令以三个连续斜杠 (`///`) 开头,通常放置在 TypeScript 文件的顶部,对运行时行为没有影响。 9 | 10 | 三斜杠指令用于引用外部依赖项、指定模块加载行为、启用/禁用某些编译器功能等等。几个例子: 11 | 12 | 引用声明文件: 13 | 14 | 15 | 16 | ```typescript 17 | /// 18 | ``` 19 | 20 | 指明模块格式: 21 | 22 | 23 | 24 | ```typescript 25 | /// 26 | ``` 27 | 28 | 启用编译器选项,在以下示例中严格模式: 29 | 30 | 31 | 32 | ```typescript 33 | /// 34 | ``` 35 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Tuple Type (Anonymous).md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 元组类型(匿名) 3 | sidebar: 4 | order: 26 5 | label: 26. 元组类型(匿名) 6 | --- 7 | 8 | 元组类型是一种表示具有固定数量的元素及其相应类型的数组的类型。元组类型以固定顺序强制执行特定数量的元素及其各自的类型。当您想要表示具有特定类型的值的集合时,元组类型非常有用,其中数组中每个元素的位置都有特定的含义。 9 | 10 | ```typescript 11 | type Point = [number, number]; 12 | ``` 13 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Type Annotations.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 类型注释 3 | sidebar: 4 | order: 9 5 | label: 9. 类型注释 6 | --- 7 | 8 | 在使用 `var` 、 `let` 和 `const` 声明变量时,可以选择添加类型: 9 | 10 | ```typescript 11 | const x: number = 1; 12 | ``` 13 | 14 | TypeScript 在推断类型方面做得很好,尤其是简单类型时,因此在大多数情况下这些声明是不必要的。 15 | 16 | 在函数上可以向参数添加类型注释: 17 | 18 | ```typescript 19 | function sum(a: number, b: number) { 20 | return a + b; 21 | } 22 | ``` 23 | 24 | 以下是使用匿名函数(所谓的 lambda 函数)的示例: 25 | 26 | ```typescript 27 | const sum = (a: number, b: number) => a + b; 28 | ``` 29 | 30 | 当参数存在默认值时可以避免这些注释: 31 | 32 | ```typescript 33 | const sum = (a = 10, b: number) => a + b; 34 | ``` 35 | 36 | 可以将返回类型注释添加到函数中: 37 | 38 | ```typescript 39 | const sum = (a = 10, b: number): number => a + b; 40 | ``` 41 | 42 | 这对于更复杂的函数尤其有用,因为在实现之前编写显式返回类型可以帮助更好地思考该函数。 43 | 44 | 通常考虑注释类型签名,但不注释主体局部变量,并始终将类型添加到对象字面量中。 45 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Type Indexing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 类型索引 3 | sidebar: 4 | order: 31 5 | label: 31. 类型索引 6 | --- 7 | 8 | 类型索引是指能够通过预先未知的键来定义可以索引的类型,使用索引签名来指定未显式声明的属性的类型。 9 | 10 | ```typescript 11 | type Dictionary = { 12 | [key: string]: T; 13 | }; 14 | const myDict: Dictionary = { a: 'a', b: 'b' }; 15 | console.log(myDict['a']); // 返回 a 16 | ``` 17 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Type Predicates.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 类型谓词 3 | sidebar: 4 | order: 21 5 | label: 21. 类型谓词 6 | --- 7 | 8 | TypeScript 中的类型谓词是返回布尔值的函数,用于将变量的类型缩小为更具体的类型。 9 | 10 | ```typescript 11 | const isString = (value: unknown): value is string => typeof value === 'string'; 12 | 13 | const foo = (bar: unknown) => { 14 | if (isString(bar)) { 15 | console.log(bar.toUpperCase()); 16 | } else { 17 | console.log('not a string'); 18 | } 19 | }; 20 | ``` 21 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Type from Func Return.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Func 返回值的类型 3 | sidebar: 4 | order: 33 5 | label: 33. Func 返回值的类型 6 | --- 7 | 8 | Func Return 中的类型是指根据函数的实现自动推断函数的返回类型的能力。这允许 TypeScript 无需显式类型注释即可确定函数返回值的类型。 9 | 10 | ```typescript 11 | const add = (x: number, y: number) => x + y; // TypeScript 可以推断函数的返回类型是数字 12 | ``` 13 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Type from Module.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 模块的类型 3 | sidebar: 4 | order: 34 5 | label: 34. 模块的类型 6 | --- 7 | 8 | 模块的类型是指使用模块的导出值自动推断其类型的能力。当模块导出特定类型的值时,TypeScript 可以使用该信息在将该值导入到另一个模块时自动推断该值的类型。 9 | 10 | 11 | 12 | ```typescript 13 | export const add = (x: number, y: number) => x + y; 14 | // index.ts 15 | import { add } from 'calc'; 16 | const r = add(1, 2); // r 是 number 类型 17 | ``` 18 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Type from Value.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 值的类型 3 | sidebar: 4 | order: 32 5 | label: 32. 值的类型 6 | --- 7 | 8 | TypeScript 中的"Type from Value"是指通过类型推断从值或表达式自动推断出类型。 9 | 10 | ```typescript 11 | const x = 'x'; // TypeScript 可以自动推断变量的类型是 string 12 | ``` 13 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Union Type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 联合类型 3 | sidebar: 4 | order: 29 5 | label: 29. 联合类型 6 | --- 7 | 8 | 联合类型是一种表示值的类型,该值可以是多种类型之一。联合类型使用 `|` 表示 每种可能类型之间的符号。 9 | 10 | ```typescript 11 | let x: string | number; 12 | x = 'hello'; // 有效 13 | x = 123; // 有效 14 | ``` 15 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Unknown type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 未知类型 3 | sidebar: 4 | order: 43 5 | label: 43. 未知类型 6 | --- 7 | 8 | 在 TypeScript 中,未知类型表示未知类型的值。与允许任何类型值的 `any` 类型不同,`unknown` 需要在以特定方式使用它之前进行类型检查或断言,因此在未首先断言或缩小到更具体的类型的情况下,不允许对 `unknown` 进行任何操作 。 9 | 10 | `unknown` 类型只能分配给任何类型和未知类型本身,它是any 的类型安全替代方案。 11 | 12 | 13 | 14 | ```typescript 15 | let value: unknown; 16 | 17 | let value1: unknown = value; // 有效 18 | let value2: any = value; // 有效 19 | let value3: boolean = value; // 无效 20 | let value4: number = value; // 无效 21 | ``` 22 | 23 | ```typescript 24 | const add = (a: unknown, b: unknown): number | undefined => 25 | typeof a === 'number' && typeof b === 'number' ? a + b : undefined; 26 | console.log(add(1, 2)); // 3 27 | console.log(add('x', 2)); // undefined 28 | ``` 29 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/Void type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 空类型 3 | sidebar: 4 | order: 44 5 | label: 44. 空类型 6 | --- 7 | 8 | `void` 类型用于指示函数不返回值。 9 | 10 | ```typescript 11 | const sayHello = (): void => { 12 | console.log('Hello!'); 13 | }; 14 | ``` 15 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/infer Type Inference in Conditional Types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: infer 条件类型中的类型推断 3 | sidebar: 4 | order: 39 5 | label: 39. infer 条件类型中的类型推断 6 | --- 7 | 8 | `infer` 关键字在条件类型中使用,用于从依赖于泛型参数的类型中推断(提取)泛型参数的类型。这允许您编写更灵活且可重用的类型定义。 9 | 10 | ```typescript 11 | type ElementType = T extends (infer U)[] ? U : never; 12 | type Numbers = ElementType; // number 13 | type Strings = ElementType; // string 14 | ``` 15 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/books/strictNullChecks.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 严格空检查 3 | sidebar: 4 | order: 16 5 | label: 16. 严格空检查 6 | --- 7 | 8 | `strictNullChecks` 是一个 TypeScript 编译器选项,强制执行严格的 null 检查。启用此选项后,只有在变量和参数已使用联合类型 `null` | `undefined` 显式声明为该类型时,才可以对其进行赋值`null` 或者 `undefined`。如果变量或参数未显式声明为可为空,TypeScript 将生成错误以防止潜在的运行时错误。 9 | -------------------------------------------------------------------------------- /website-astro/src/content/docs/zh-cn/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Typescript Book 3 | description: The Concise TypeScript Book 4 | template: splash 5 | hero: 6 | tagline: 7 | 《Concise TypeScript Book》全面而简洁地概述了 TypeScript 8 | 的功能。它提供了清晰的解释,涵盖了该语言最新版本中的所有方面,从强大的类型系统到高级功能。无论您是初学者还是经验丰富的开发人员,本书都是增强您对 9 | TypeScript 的理解和熟练程度的宝贵资源。

本书完全免费且开源。 10 | actions: 11 | - text: 开始阅读! 12 | link: /zh-cn/books/the-concise-typescript-book/ 13 | icon: right-arrow 14 | variant: primary 15 | --- 16 | -------------------------------------------------------------------------------- /website-astro/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /website-astro/src/styles/global.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --sl-color-text-accent: #3178c6; 3 | --sl-color-text-invert: #fff; 4 | } 5 | -------------------------------------------------------------------------------- /website-astro/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from 'tailwindcss' 2 | 3 | import starlightPlugin from '@astrojs/starlight-tailwind' 4 | 5 | export default { 6 | content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}', 'node_modules/@color-kit/**/*'], 7 | plugins: [starlightPlugin()], 8 | theme: { 9 | extend: {}, 10 | }, 11 | } satisfies Config 12 | -------------------------------------------------------------------------------- /website-astro/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/strict", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@color-kit/crystal": ["../../packages/crystal/src"] 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | # generated types 4 | .astro/ 5 | 6 | # dependencies 7 | node_modules/ 8 | 9 | # logs 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | pnpm-debug.log* 14 | 15 | 16 | # environment variables 17 | .env 18 | .env.production 19 | 20 | # macOS-specific files 21 | .DS_Store 22 | -------------------------------------------------------------------------------- /website/.nvmrc: -------------------------------------------------------------------------------- 1 | v19.7.0 2 | -------------------------------------------------------------------------------- /website/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 4, 4 | "semi": true, 5 | "singleQuote": true, 6 | "printWidth": 80, 7 | "arrowParens": "avoid" 8 | } -------------------------------------------------------------------------------- /website/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["astro-build.astro-vscode"], 3 | "unwantedRecommendations": [] 4 | } 5 | -------------------------------------------------------------------------------- /website/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "command": "./node_modules/.bin/astro dev", 6 | "name": "Development server", 7 | "request": "launch", 8 | "type": "node-terminal" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | # Starlight Starter Kit: Basics 2 | 3 | [![Built with Starlight](https://astro.badg.es/v2/built-with-starlight/tiny.svg)](https://starlight.astro.build) 4 | 5 | ``` 6 | npm create astro@latest -- --template starlight 7 | ``` 8 | 9 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics) 10 | [![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/starlight/tree/main/examples/basics) 11 | [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fwithastro%2Fstarlight%2Ftree%2Fmain%2Fexamples%2Fbasics&project-name=my-starlight-docs&repository-name=my-starlight-docs) 12 | 13 | > 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun! 14 | 15 | ## 🚀 Project Structure 16 | 17 | Inside of your Astro + Starlight project, you'll see the following folders and files: 18 | 19 | ``` 20 | . 21 | ├── public/ 22 | ├── src/ 23 | │ ├── assets/ 24 | │ ├── content/ 25 | │ │ ├── docs/ 26 | │ │ └── config.ts 27 | │ └── env.d.ts 28 | ├── astro.config.mjs 29 | ├── package.json 30 | └── tsconfig.json 31 | ``` 32 | 33 | Starlight looks for `.md` or `.mdx` files in the `src/content/docs/` directory. Each file is exposed as a route based on its file name. 34 | 35 | Images can be added to `src/assets/` and embedded in Markdown with a relative link. 36 | 37 | Static assets, like favicons, can be placed in the `public/` directory. 38 | 39 | ## 🧞 Commands 40 | 41 | All commands are run from the root of the project, from a terminal: 42 | 43 | | Command | Action | 44 | | :------------------------ | :----------------------------------------------- | 45 | | `npm install` | Installs dependencies | 46 | | `npm run dev` | Starts local dev server at `localhost:4321` | 47 | | `npm run build` | Build your production site to `./dist/` | 48 | | `npm run preview` | Preview your build locally, before deploying | 49 | | `npm run astro ...` | Run CLI commands like `astro add`, `astro check` | 50 | | `npm run astro -- --help` | Get help using the Astro CLI | 51 | 52 | ## 👀 Want to learn more? 53 | 54 | Check out [Starlight’s docs](https://starlight.astro.build/), read [the Astro documentation](https://docs.astro.build), or jump into the [Astro Discord server](https://astro.build/chat). 55 | -------------------------------------------------------------------------------- /website/astro.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'astro/config'; 2 | import starlight from '@astrojs/starlight'; 3 | 4 | // https://astro.build/config 5 | export default defineConfig({ 6 | site: 'https://gibbok.github.io', 7 | base: '/typescript-book', 8 | build: { 9 | assets: 'app_assets', 10 | }, 11 | integrations: [ 12 | starlight({ 13 | title: 'TypeScript Book', 14 | customCss: ['./src/styles/custom.css'], 15 | social: { 16 | github: 'https://github.com/gibbok/typescript-book', 17 | 'x.com': 'https://twitter.com/gibbok_coding', 18 | }, 19 | defaultLocale: 'root', 20 | locales: { 21 | root: { 22 | label: 'English', 23 | lang: 'en', 24 | }, 25 | 'zh-cn': { 26 | label: '简体中文', 27 | lang: 'zh-CN', 28 | }, 29 | }, 30 | sidebar: [ 31 | { 32 | label: 'TypeScript Book', 33 | autogenerate: { directory: 'book' }, 34 | }, 35 | ], 36 | }), 37 | ], 38 | }); 39 | -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "website", 3 | "type": "module", 4 | "version": "0.0.1", 5 | "scripts": { 6 | "dev": "astro dev", 7 | "start": "astro dev", 8 | "build": "astro check && astro build", 9 | "preview": "astro preview", 10 | "astro": "astro", 11 | "deploy": "npm run build && npx gh-pages -d dist" 12 | }, 13 | "dependencies": { 14 | "@astrojs/check": "^0.4.1", 15 | "@astrojs/starlight": "^0.15.3", 16 | "astro": "^4.0.1", 17 | "sharp": "^0.32.5", 18 | "typescript": "^5.3.3" 19 | }, 20 | "devDependencies": { 21 | "gh-pages": "^6.1.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /website/public/favicon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /website/src/assets/houston.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nnecec/typescript-book/f042af63e3471f5dc7e8f1450f87e0f57398f5e9/website/src/assets/houston.webp -------------------------------------------------------------------------------- /website/src/content/config.ts: -------------------------------------------------------------------------------- 1 | import { defineCollection } from 'astro:content'; 2 | import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; 3 | 4 | export const collections = { 5 | docs: defineCollection({ schema: docsSchema() }), 6 | i18n: defineCollection({ type: 'data', schema: i18nSchema() }), 7 | }; 8 | -------------------------------------------------------------------------------- /website/src/content/docs/book/about-the-author.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: About the Author 3 | sidebar: 4 | order: 6 5 | label: 6. About the Author 6 | --- 7 | 8 | 9 | Simone Poggiali is an experienced Senior Front-end Developer with a passion for writing professional-grade code since the 90s. Throughout his international career, he has contributed to numerous projects for a wide range of clients, from startups to large organizations. Notable companies such as HelloFresh, Siemens, O2, and Leroy Merlin have benefited from his expertise and dedication. 10 | 11 | You can reach Simone Poggiali on the following platforms: 12 | 13 | * LinkedIn: [https://www.linkedin.com/in/simone-poggiali](https://www.linkedin.com/in/simone-poggiali) 14 | * GitHub: [https://github.com/gibbok](https://github.com/gibbok) 15 | * X.com: [https://x.com/gibbok_coding](https://x.com/gibbok_coding) 16 | * Email: gibbok.coding📧gmail.com 17 | 18 | -------------------------------------------------------------------------------- /website/src/content/docs/book/any-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Any type 3 | sidebar: 4 | order: 44 5 | label: 44. Any type 6 | --- 7 | 8 | 9 | The `any` type is a special type (universal supertype) that can be used to represent any type of value (primitives, objects, arrays, functions, errors, symbols). It is often used in situations where the type of a value is not known at compile time, or when working with values from external APIs or libraries that do not have TypeScript typings. 10 | 11 | By utilizing `any` type, you are indicating to the TypeScript compiler that values should be represented without any limitations. In order to maximizing type safety in your code consider the following: 12 | 13 | * Limit the usage of `any` to specific cases where the type is truly unknown. 14 | * Do not return `any` types from a function as you will lose type safety in the code using that function weakening your type safety. 15 | * Instead of `any` use `@ts-ignore` if you need to silence the compiler. 16 | 17 | ```typescript 18 | let value: any; 19 | value = true; // Valid 20 | value = 7; // Valid 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /website/src/content/docs/book/assignments.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Assignments 3 | sidebar: 4 | order: 21 5 | label: 21. Assignments 6 | --- 7 | 8 | 9 | TypeScript narrowing using assignments is a way to narrow the type of a variable based on the value assigned to it. When a variable is assigned a value, TypeScript infers its type based on the assigned value, and it narrows the type of the variable to match the inferred type. 10 | 11 | ```typescript 12 | let value: string | number; 13 | value = 'hello'; 14 | if (typeof value === 'string') { 15 | console.log(value.toUpperCase()); 16 | } 17 | value = 42; 18 | if (typeof value === 'number') { 19 | console.log(value.toFixed(2)); 20 | } 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /website/src/content/docs/book/built-in-type-primitives.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Built-in Type Primitives 3 | sidebar: 4 | order: 49 5 | label: 49. Built-in Type Primitives 6 | --- 7 | 8 | 9 | TypeScript has several built-in type primitives that can be used to define variables, function parameters, and return types: 10 | 11 | * `number`: Represents numeric values, including integers and floating-point numbers. 12 | * `string`: Represents textual data 13 | * `boolean`: Represents logical values, which can be either true or false. 14 | * `null`: Represents the absence of a value. 15 | * `undefined`: Represents a value that has not been assigned or has not been defined. 16 | * `symbol`: Represents a unique identifier. Symbols are typically used as keys for object properties. 17 | * `bigint`: Represents arbitrary-precision integers. 18 | * `any`: Represents a dynamic or unknown type. Variables of type any can hold values of any type, and they bypass type checking. 19 | * `void`: Represents the absence of any type. It is commonly used as the return type of functions that do not return a value. 20 | * `never`: Represents a type for values that never occur. It is typically used as the return type of functions that throw an error or enter an infinite loop. 21 | 22 | -------------------------------------------------------------------------------- /website/src/content/docs/book/common-built-in-js-objects.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Common Built-in JS Objects 3 | sidebar: 4 | order: 50 5 | label: 50. Common Built-in JS Objects 6 | --- 7 | 8 | 9 | TypeScript is a superset of JavaScript, it includes all the commonly used built-in JavaScript objects. You can find an extensive list of these objects on the Mozilla Developer Network (MDN) documentation website: 10 | [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects) 11 | 12 | Here is a list of some commonly used built-in JavaScript objects: 13 | 14 | * Function 15 | * Object 16 | * Boolean 17 | * Error 18 | * Number 19 | * BigInt 20 | * Math 21 | * Date 22 | * String 23 | * RegExp 24 | * Array 25 | * Map 26 | * Set 27 | * Promise 28 | * Intl 29 | 30 | -------------------------------------------------------------------------------- /website/src/content/docs/book/conditional-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Conditional Types 3 | sidebar: 4 | order: 39 5 | label: 39. Conditional Types 6 | --- 7 | 8 | 9 | Conditional Types are a way to create a type that depends on a condition, where the type to be created is determined based on the result of the condition. They are defined using the `extends` keyword and a ternary operator to conditionally choose between two types. 10 | 11 | ```typescript 12 | type IsArray = T extends any[] ? true : false; 13 | 14 | const myArray = [1, 2, 3]; 15 | const myNumber = 42; 16 | 17 | type IsMyArrayAnArray = IsArray; // Type true 18 | type IsMyNumberAnArray = IsArray; // Type false 19 | ``` 20 | 21 | -------------------------------------------------------------------------------- /website/src/content/docs/book/control-flow-analysis.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Control Flow Analysis 3 | sidebar: 4 | order: 22 5 | label: 22. Control Flow Analysis 6 | --- 7 | 8 | 9 | Control Flow Analysis in TypeScript is a way to statically analyze the code flow to infer the types of variables, allowing the compiler to narrow the types of those variables as needed, based on the results of the analysis. 10 | 11 | Prior to TypeScript 4.4, code flow analysis would only be applied to code within an if statement, but from TypeScript 4.4, it can also be applied to conditional expressions and discriminant property accesses indirectly referenced through const variables. 12 | 13 | For example: 14 | 15 | ```typescript 16 | const f1 = (x: unknown) => { 17 | const isString = typeof x === 'string'; 18 | if (isString) { 19 | x.length; 20 | } 21 | }; 22 | 23 | const f2 = ( 24 | obj: { kind: 'foo'; foo: string } | { kind: 'bar'; bar: number } 25 | ) => { 26 | const isFoo = obj.kind === 'foo'; 27 | if (isFoo) { 28 | obj.foo; 29 | } else { 30 | obj.bar; 31 | } 32 | }; 33 | ``` 34 | 35 | Some examples where narrowing does not occur: 36 | 37 | 38 | ```typescript 39 | const f1 = (x: unknown) => { 40 | let isString = typeof x === 'string'; 41 | if (isString) { 42 | x.length; // Error, no narrowing because isString it is not const 43 | } 44 | }; 45 | 46 | const f6 = ( 47 | obj: { kind: 'foo'; foo: string } | { kind: 'bar'; bar: number } 48 | ) => { 49 | const isFoo = obj.kind === 'foo'; 50 | obj = obj; 51 | if (isFoo) { 52 | obj.foo; // Error, no narrowing because obj is assigned in function body 53 | } 54 | }; 55 | ``` 56 | 57 | Notes: Up to five levels of indirection are analyzed in conditional expressions. 58 | 59 | -------------------------------------------------------------------------------- /website/src/content/docs/book/differences-between-type-and-interface.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Differences between Type and Interface 3 | sidebar: 4 | order: 53 5 | label: 53. Differences between Type and Interface 6 | --- 7 | 8 | 9 | Declaration merging (augmentation): 10 | 11 | Interfaces support declaration merging, which means that you can define multiple interfaces with the same name, and TypeScript will merge them into a single interface with the combined properties and methods. On the other hand, types do not support declaration merging. This can be helpful when you want to add extra functionality or customize existing types without modifying the original definitions or patching missing or incorrect types. 12 | 13 | ```typescript 14 | interface A { 15 | x: string; 16 | } 17 | interface A { 18 | y: string; 19 | } 20 | const j: A = { 21 | x: 'xx', 22 | y: 'yy', 23 | }; 24 | ``` 25 | 26 | Extending other types/interfaces: 27 | 28 | Both types and interfaces can extend other types/interfaces, but the syntax is different. With interfaces, you use the `extends` keyword to inherit properties and methods from other interfaces. However, an interface cannot extend a complex type like a union type. 29 | 30 | ```typescript 31 | interface A { 32 | x: string; 33 | y: number; 34 | } 35 | interface B extends A { 36 | z: string; 37 | } 38 | const car: B = { 39 | x: 'x', 40 | y: 123, 41 | z: 'z', 42 | }; 43 | ``` 44 | 45 | For types, you use the & operator to combine multiple types into a single type (intersection). 46 | 47 | ```typescript 48 | interface A { 49 | x: string; 50 | y: number; 51 | } 52 | 53 | type B = A & { 54 | j: string; 55 | }; 56 | 57 | const c: B = { 58 | x: 'x', 59 | y: 123, 60 | j: 'j', 61 | }; 62 | ``` 63 | 64 | Union and Intersection Types: 65 | 66 | Types are more flexible when it comes to defining Union and Intersection Types. With the `type` keyword, you can easily create union types using the `|` operator and intersection types using the `&` operator. While interfaces can also represent union types indirectly, they don't have built-in support for intersection types. 67 | 68 | ```typescript 69 | type Department = 'dep-x' | 'dep-y'; // Union 70 | 71 | type Person = { 72 | name: string; 73 | age: number; 74 | }; 75 | 76 | type Employee = { 77 | id: number; 78 | department: Department; 79 | }; 80 | 81 | type EmployeeInfo = Person & Employee; // Intersection 82 | ``` 83 | 84 | Example with interfaces: 85 | 86 | ```typescript 87 | interface A { 88 | x: 'x'; 89 | } 90 | interface B { 91 | y: 'y'; 92 | } 93 | 94 | type C = A | B; // Union of interfaces 95 | ``` 96 | 97 | -------------------------------------------------------------------------------- /website/src/content/docs/book/discriminated-unions.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Discriminated Unions 3 | sidebar: 4 | order: 24 5 | label: 24. Discriminated Unions 6 | --- 7 | 8 | 9 | Discriminated Unions in TypeScript are a type of union type that uses a common property, known as the discriminant, to narrow down the set of possible types for the union. 10 | 11 | ```typescript 12 | type Square = { 13 | kind: 'square'; // Discriminant 14 | size: number; 15 | }; 16 | 17 | type Circle = { 18 | kind: 'circle'; // Discriminant 19 | radius: number; 20 | }; 21 | 22 | type Shape = Square | Circle; 23 | 24 | const area = (shape: Shape) => { 25 | switch (shape.kind) { 26 | case 'square': 27 | return Math.pow(shape.size, 2); 28 | case 'circle': 29 | return Math.PI * Math.pow(shape.radius, 2); 30 | } 31 | }; 32 | 33 | const square: Square = { kind: 'square', size: 5 }; 34 | const circle: Circle = { kind: 'circle', radius: 2 }; 35 | 36 | console.log(area(square)); // 25 37 | console.log(area(circle)); // 12.566370614359172 38 | ``` 39 | 40 | -------------------------------------------------------------------------------- /website/src/content/docs/book/distributive-conditional-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Distributive Conditional Types 3 | sidebar: 4 | order: 40 5 | label: 40. Distributive Conditional Types 6 | --- 7 | 8 | 9 | Distributive Conditional Types are a feature that allow a type to be distributed over a union of types, by applying a transformation to each member of the union individually. 10 | This can be especially useful when working with mapped types or higher-order types. 11 | 12 | ```typescript 13 | type Nullable = T extends any ? T | null : never; 14 | type NumberOrBool = number | boolean; 15 | type NullableNumberOrBool = Nullable; // number | boolean | null 16 | ``` 17 | 18 | -------------------------------------------------------------------------------- /website/src/content/docs/book/downloads-and-website.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Downloads and website 3 | sidebar: 4 | order: 3 5 | label: 3. Downloads and website 6 | --- 7 | 8 | 9 | You can also download the Epub version: 10 | 11 | [https://github.com/gibbok/typescript-book/tree/main/downloads](https://github.com/gibbok/typescript-book/tree/main/downloads) 12 | 13 | An online version is available at: 14 | 15 | [https://gibbok.github.io/typescript-book](https://gibbok.github.io/typescript-book) 16 | 17 | -------------------------------------------------------------------------------- /website/src/content/docs/book/erased-structural-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Erased Structural Types 3 | sidebar: 4 | order: 56 5 | label: 56. Erased Structural Types 6 | --- 7 | 8 | 9 | In TypeScript, objects do not have to match a specific, exact type. For instance, if we create an object that fulfills an interface's requirements, we can utilize that object in places where that interface is required, even if there was no explicit connection between them. 10 | Example: 11 | 12 | ```typescript 13 | type NameProp1 = { 14 | prop1: string; 15 | }; 16 | 17 | function log(x: NameProp1) { 18 | console.log(x.prop1); 19 | } 20 | 21 | const obj = { 22 | prop2: 123, 23 | prop1: 'Origin', 24 | }; 25 | 26 | log(obj); // Valid 27 | ``` 28 | 29 | -------------------------------------------------------------------------------- /website/src/content/docs/book/exhaustiveness-checking.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Exhaustiveness checking 3 | sidebar: 4 | order: 26 5 | label: 26. Exhaustiveness checking 6 | --- 7 | 8 | 9 | Exhaustiveness checking is a feature in TypeScript that ensures all possible cases of a discriminated union are handled in a `switch` statement or an `if` statement. 10 | 11 | ```typescript 12 | type Direction = 'up' | 'down'; 13 | 14 | const move = (direction: Direction) => { 15 | switch (direction) { 16 | case 'up': 17 | console.log('Moving up'); 18 | break; 19 | case 'down': 20 | console.log('Moving down'); 21 | break; 22 | default: 23 | const exhaustiveCheck: never = direction; 24 | console.log(exhaustiveCheck); // This line will never be executed 25 | } 26 | }; 27 | ``` 28 | 29 | The `never` type is used to ensure that the default case is exhaustive and that TypeScript will raise an error if a new value is added to the Direction type without being handled in the switch statement. 30 | 31 | -------------------------------------------------------------------------------- /website/src/content/docs/book/extending-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Extending Types 3 | sidebar: 4 | order: 15 5 | label: 15. Extending Types 6 | --- 7 | 8 | 9 | It is possible to extend an `interface` (copy members from another type): 10 | 11 | ```typescript 12 | interface X { 13 | a: string; 14 | } 15 | interface Y extends X { 16 | b: string; 17 | } 18 | ``` 19 | 20 | It is also possible to extend from multiple types: 21 | 22 | ```typescript 23 | interface A { 24 | a: string; 25 | } 26 | interface B { 27 | b: string; 28 | } 29 | interface Y extends A, B { 30 | y: string; 31 | } 32 | ``` 33 | 34 | The `extends` keyword works only on interfaces and classes, for types use an intersection: 35 | 36 | ```typescript 37 | type A = { 38 | a: number; 39 | }; 40 | type B = { 41 | b: number; 42 | }; 43 | type C = A & B; 44 | ``` 45 | 46 | It is possible to extend a type using an inference but not vice versa: 47 | 48 | ```typescript 49 | type A = { 50 | a: string; 51 | }; 52 | interface B extends A { 53 | b: string; 54 | } 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /website/src/content/docs/book/fixed-length-tuple.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Fixed Length Tuple 3 | sidebar: 4 | order: 30 5 | label: 30. Fixed Length Tuple 6 | --- 7 | 8 | 9 | A Fixed Length Tuple is a specific type of tuple that enforces a fixed number of elements of specific types, and disallows any modifications to the length of the tuple once it is defined. 10 | 11 | Fixed Length Tuples are useful when you need to represent a collection of values with a specific number of elements and specific types, and you want to ensure that the length and types of the tuple cannot be changed inadvertently. 12 | 13 | 14 | ```typescript 15 | const x = [10, 'hello'] as const; 16 | x.push(2); // Error 17 | ``` 18 | 19 | -------------------------------------------------------------------------------- /website/src/content/docs/book/index-signatures.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Index Signatures 3 | sidebar: 4 | order: 14 5 | label: 14. Index Signatures 6 | --- 7 | 8 | 9 | In TypeScript we can use as index signature `string`, `number`, and `symbol`: 10 | 11 | ```typescript 12 | type K = { 13 | [name: string | number]: string; 14 | }; 15 | const k: K = { x: 'x', 1: 'b' }; 16 | console.log(k['x']); 17 | console.log(k[1]); 18 | console.log(k['1']); // Same result as k[1] 19 | ``` 20 | 21 | Please note that JavaScript automatically converts an index with `number` to an index with `string` so `k[1]` or `k["1"]` return the same value. 22 | 23 | -------------------------------------------------------------------------------- /website/src/content/docs/book/infer-type-inference-in-conditional-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: infer Type Inference in Conditional Types 3 | sidebar: 4 | order: 41 5 | label: 41. infer Type Inference in Conditional Types 6 | --- 7 | 8 | 9 | The `infer`keyword is used in conditional types to infer (extract) the type of a generic parameter from a type that depends on it. This allows you to write more flexible and reusable type definitions. 10 | 11 | ```typescript 12 | type ElementType = T extends (infer U)[] ? U : never; 13 | type Numbers = ElementType; // number 14 | type Strings = ElementType; // string 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /website/src/content/docs/book/interface-and-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Interface and Type 3 | sidebar: 4 | order: 48 5 | label: 48. Interface and Type 6 | --- 7 | 8 | 9 | ### Common Syntax 10 | 11 | In TypeScript, interfaces define the structure of objects, specifying the names and types of properties or methods that an object must have. The common syntax for defining an interface in TypeScript is as follows: 12 | 13 | 14 | ```typescript 15 | interface InterfaceName { 16 | property1: Type1; 17 | // ... 18 | method1(arg1: ArgType1, arg2: ArgType2): ReturnType; 19 | // ... 20 | } 21 | ``` 22 | 23 | Similarly for type definition: 24 | 25 | 26 | ```typescript 27 | type TypeName = { 28 | property1: Type1; 29 | // ... 30 | method1(arg1: ArgType1, arg2: ArgType2): ReturnType; 31 | // ... 32 | }; 33 | ``` 34 | 35 | `interface InterfaceName` or `type TypeName`: Defines the name of the interface. 36 | `property1`: `Type1`: Specifies the properties of the interface along with their corresponding types. Multiple properties can be defined, each separated by a semicolon. 37 | `method1(arg1: ArgType1, arg2: ArgType2): ReturnType;`: Specifies the methods of the interface. Methods are defined with their names, followed by a parameter list in parentheses and the return type. Multiple methods can be defined, each separated by a semicolon. 38 | 39 | Example interface: 40 | 41 | ```typescript 42 | interface Person { 43 | name: string; 44 | age: number; 45 | greet(): void; 46 | } 47 | ``` 48 | 49 | Example of type: 50 | 51 | ```typescript 52 | type TypeName = { 53 | property1: string; 54 | method1(arg1: string, arg2: string): string; 55 | }; 56 | ``` 57 | 58 | In TypeScript, types are used to define the shape of data and enforce type checking. There are several common syntaxes for defining types in TypeScript, depending on the specific use case. Here are some examples: 59 | 60 | ### Basic Types 61 | 62 | ```typescript 63 | let myNumber: number = 123; // number type 64 | let myBoolean: boolean = true; // boolean type 65 | let myArray: string[] = ['a', 'b']; // array of strings 66 | let myTuple: [string, number] = ['a', 123]; // tuple 67 | ``` 68 | 69 | ### Objects and Interfaces 70 | 71 | ```typescript 72 | const x: { name: string; age: number } = { name: 'Simon', age: 7 }; 73 | ``` 74 | 75 | ### Union and Intersection Types 76 | 77 | ```typescript 78 | type MyType = string | number; // Union type 79 | let myUnion: MyType = 'hello'; // Can be a string 80 | myUnion = 123; // Or a number 81 | 82 | type TypeA = { name: string }; 83 | type TypeB = { age: number }; 84 | type CombinedType = TypeA & TypeB; // Intersection type 85 | let myCombined: CombinedType = { name: 'John', age: 25 }; // Object with both name and age properties 86 | ``` 87 | 88 | -------------------------------------------------------------------------------- /website/src/content/docs/book/intersection-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Intersection Types 3 | sidebar: 4 | order: 32 5 | label: 32. Intersection Types 6 | --- 7 | 8 | 9 | An Intersection Type is a type that represents a value that has all the properties of two or more types. Intersection Types are denoted using the `&` symbol between each type. 10 | 11 | ```typescript 12 | type X = { 13 | a: string; 14 | }; 15 | 16 | type Y = { 17 | b: string; 18 | }; 19 | 20 | type J = X & Y; // Intersection 21 | 22 | const j: J = { 23 | a: 'a', 24 | b: 'b', 25 | }; 26 | ``` 27 | 28 | -------------------------------------------------------------------------------- /website/src/content/docs/book/introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction 3 | sidebar: 4 | order: 5 5 | label: 5. Introduction 6 | --- 7 | 8 | 9 | Welcome to The Concise TypeScript Book! This guide equips you with essential knowledge and practical skills for effective TypeScript development. Discover key concepts and techniques to write clean, robust code. Whether you're a beginner or an experienced developer, this book serves as both a comprehensive guide and a handy reference for leveraging TypeScript's power in your projects. 10 | 11 | This book covers TypeScript 5.2. 12 | 13 | -------------------------------------------------------------------------------- /website/src/content/docs/book/literal-inference.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Literal Inference 3 | sidebar: 4 | order: 17 5 | label: 17. Literal Inference 6 | --- 7 | 8 | 9 | Literal Inference is a feature in TypeScript that allows the type of a variable or parameter to be inferred based on its value. 10 | 11 | In the following example we can see that TypeScript considers `x` a literal type as the value cannot be changed any time later, when instead `y` is inferred as string as it can be modified any time later. 12 | 13 | ```typescript 14 | const x = 'x'; // Literal type of 'x', because this value cannot be changed 15 | let y = 'y'; // Type string, as we can change this value 16 | ``` 17 | 18 | In the following example we can see that `o.x` was inferred as a `string` (and not a literal of `a`) as TypeScript considers that the value can be changed any time later. 19 | 20 | 21 | ```typescript 22 | type X = 'a' | 'b'; 23 | 24 | let o = { 25 | x: 'a', // This is a wider string 26 | }; 27 | 28 | const fn = (x: X) => `${x}-foo`; 29 | 30 | console.log(fn(o.x)); // Argument of type 'string' is not assignable to parameter of type 'X' 31 | ``` 32 | 33 | As you can see the code throws an error when passing `o.x` to `fn` as X is a narrower type. 34 | 35 | We can solve this issue by using type assertion using `const` or the `X` type: 36 | 37 | 38 | ```typescript 39 | let o = { 40 | x: 'a' as const, 41 | }; 42 | ``` 43 | 44 | or: 45 | 46 | 47 | ```typescript 48 | let o = { 49 | x: 'a' as X, 50 | }; 51 | ``` 52 | 53 | -------------------------------------------------------------------------------- /website/src/content/docs/book/literal-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Literal Types 3 | sidebar: 4 | order: 16 5 | label: 16. Literal Types 6 | --- 7 | 8 | 9 | A Literal Type is a single element set from a collective type, it defines a very exact value that is a JavaScript primitive. 10 | 11 | Literal Types in TypeScript are numbers, strings, and booleans. 12 | 13 | Example of literals: 14 | 15 | ```typescript 16 | const a = 'a'; // String literal type 17 | const b = 1; // Numeric literal type 18 | const c = true; // Boolean literal type 19 | ``` 20 | 21 | String, Numeric, and Boolean Literal Types are used in the union, type guard, and type aliases. 22 | In the following example you can see a type alias union, `O` can be the only value specified and not any other string: 23 | 24 | ```typescript 25 | type O = 'a' | 'b' | 'c'; 26 | ``` 27 | 28 | -------------------------------------------------------------------------------- /website/src/content/docs/book/mapped-type-modifiers.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Mapped Type Modifiers 3 | sidebar: 4 | order: 38 5 | label: 38. Mapped Type Modifiers 6 | --- 7 | 8 | 9 | Mapped Type Modifiers in TypeScript enable the transformation of properties within an existing type: 10 | 11 | * `readonly` or `+readonly`: This renders a property in the mapped type as read-only. 12 | * `-readonly`: This allows a property in the mapped type to be mutable. 13 | * `?`: This designates a property in the mapped type as optional. 14 | 15 | Examples: 16 | 17 | ```typescript 18 | type ReadOnly = { readonly [P in keyof T]: T[P] }; // All properties marked as read-only 19 | 20 | type Mutable = { -readonly [P in keyof T]: T[P] }; // All properties marked as mutable 21 | 22 | type MyPartial = { [P in keyof T]?: T[P] }; // All properties marked as optional 23 | ``` 24 | 25 | -------------------------------------------------------------------------------- /website/src/content/docs/book/mapped-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Mapped Types 3 | sidebar: 4 | order: 37 5 | label: 37. Mapped Types 6 | --- 7 | 8 | 9 | Mapped Types in TypeScript allow you to create new types based on an existing type by transforming each property using a mapping function. By mapping existing types, you can create new types that represent the same information in a different format. To create a mapped type, you access the properties of an existing type using the `keyof` operator and then alter them to produce a new type. 10 | In the following example: 11 | 12 | ```typescript 13 | type MyMappedType = { 14 | [P in keyof T]: T[P][]; 15 | }; 16 | type MyType = { 17 | foo: string; 18 | bar: number; 19 | }; 20 | type MyNewType = MyMappedType; 21 | const x: MyNewType = { 22 | foo: ['hello', 'world'], 23 | bar: [1, 2, 3], 24 | }; 25 | ``` 26 | 27 | we define MyMappedType to map over T's properties, creating a new type with each property as an array of its original type. Using this, we create MyNewType to represent the same info as MyType, but with each property as an array. 28 | 29 | -------------------------------------------------------------------------------- /website/src/content/docs/book/merging-and-extension.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Merging and Extension 3 | sidebar: 4 | order: 52 5 | label: 52. Merging and Extension 6 | --- 7 | 8 | 9 | Merging and extension refer to two different concepts related to working with types and interfaces. 10 | 11 | Merging allows you to combine multiple declarations of the same name into a single definition, for example, when you define an interface with the same name multiple times: 12 | 13 | ```typescript 14 | interface X { 15 | a: string; 16 | } 17 | 18 | interface X { 19 | b: number; 20 | } 21 | 22 | const person: X = { 23 | a: 'a', 24 | b: 7, 25 | }; 26 | ``` 27 | 28 | Extension refers to the ability to extend or inherit from existing types or interfaces to create new ones. It is a mechanism to add additional properties or methods to an existing type without modifying its original definition. Example: 29 | 30 | ```typescript 31 | interface Animal { 32 | name: string; 33 | eat(): void; 34 | } 35 | 36 | interface Bird extends Animal { 37 | sing(): void; 38 | } 39 | 40 | const dog: Bird = { 41 | name: 'Bird 1', 42 | eat() { 43 | console.log('Eating'); 44 | }, 45 | sing() { 46 | console.log('Singing'); 47 | }, 48 | }; 49 | ``` 50 | 51 | -------------------------------------------------------------------------------- /website/src/content/docs/book/named-tuple-type-labeled.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Named Tuple Type (Labeled) 3 | sidebar: 4 | order: 29 5 | label: 29. Named Tuple Type (Labeled) 6 | --- 7 | 8 | 9 | Tuple types can include optional labels or names for each element. These labels are for readability and tooling assistance, and do not affect the operations you can perform with them. 10 | 11 | ```typescript 12 | type T = string; 13 | type Tuple1 = [T, T]; 14 | type Tuple2 = [a: T, b: T]; 15 | type Tuple3 = [a: T, T]; // Named Tuple plus Anonymous Tuple 16 | ``` 17 | 18 | -------------------------------------------------------------------------------- /website/src/content/docs/book/namespacing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Namespacing 3 | sidebar: 4 | order: 57 5 | label: 57. Namespacing 6 | --- 7 | 8 | 9 | In TypeScript, namespaces are used to organize code into logical containers, preventing naming collisions and providing a way to group related code together. 10 | The usage of the `export` keywords allows access to the namespace in "outside" modules. 11 | 12 | ```typescript 13 | export namespace MyNamespace { 14 | export interface MyInterface1 { 15 | prop1: boolean; 16 | } 17 | export interface MyInterface2 { 18 | prop2: string; 19 | } 20 | } 21 | 22 | const a: MyNamespace.MyInterface1 = { 23 | prop1: true, 24 | }; 25 | ``` 26 | 27 | -------------------------------------------------------------------------------- /website/src/content/docs/book/never-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Never type 3 | sidebar: 4 | order: 47 5 | label: 47. Never type 6 | --- 7 | 8 | 9 | The `never` type represents values that never occur. It is used to denote functions or expressions that never return or throw an error. 10 | 11 | For instance an infinite loop: 12 | 13 | ```typescript 14 | const infiniteLoop = (): never => { 15 | while (true) { 16 | // do something 17 | } 18 | }; 19 | ``` 20 | 21 | Throwing an error: 22 | 23 | ```typescript 24 | const throwError = (message: string): never => { 25 | throw new Error(message); 26 | }; 27 | ``` 28 | 29 | The `never` type is useful in ensuring type safety and catching potential errors in your code. It helps TypeScript analyze and infer more precise types when used in combination with other types and control flow statements, for instance: 30 | 31 | ```typescript 32 | type Direction = 'up' | 'down'; 33 | const move = (direction: Direction): void => { 34 | switch (direction) { 35 | case 'up': 36 | // move up 37 | break; 38 | case 'down': 39 | // move down 40 | break; 41 | default: 42 | const exhaustiveCheck: never = direction; 43 | throw new Error(`Unhandled direction: ${exhaustiveCheck}`); 44 | } 45 | }; 46 | ``` 47 | 48 | -------------------------------------------------------------------------------- /website/src/content/docs/book/object-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Object Types 3 | sidebar: 4 | order: 27 5 | label: 27. Object Types 6 | --- 7 | 8 | 9 | In TypeScript, object types describe the shape of an object. They specify the names and types of the object's properties, as well as whether those properties are required or optional. 10 | 11 | In TypeScript, you can define object types in two primary ways: 12 | 13 | Interface which defines the shape of an object by specifying the names, types, and optionality of its properties. 14 | 15 | ```typescript 16 | interface User { 17 | name: string; 18 | age: number; 19 | email?: string; 20 | } 21 | ``` 22 | 23 | Type alias, similar to an interface, defines the shape of an object. However, it can also create a new custom type that is based on an existing type or a combination of existing types. This includes defining union types, intersection types, and other complex types. 24 | 25 | ```typescript 26 | type Point = { 27 | x: number; 28 | y: number; 29 | }; 30 | ``` 31 | 32 | It also possible to define a type anonymously: 33 | 34 | ```typescript 35 | const sum = (x: { a: number; b: number }) => x.a + x.b; 36 | console.log(sum({ a: 5, b: 1 })); 37 | ``` 38 | 39 | -------------------------------------------------------------------------------- /website/src/content/docs/book/optional-properties.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Optional Properties 3 | sidebar: 4 | order: 12 5 | label: 12. Optional Properties 6 | --- 7 | 8 | 9 | An object can specify Optional Properties by adding a question mark `?` to the end of the property name: 10 | 11 | ```typescript 12 | type X = { 13 | a: number; 14 | b?: number; // Optional 15 | }; 16 | ``` 17 | 18 | It is possible to specify a default value when a property is optional" 19 | 20 | ```typescript 21 | type X = { 22 | a: number; 23 | b?: number; 24 | }; 25 | const x = ({ a, b = 100 }: X) => a + b; 26 | ``` 27 | 28 | -------------------------------------------------------------------------------- /website/src/content/docs/book/overloads.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Overloads 3 | sidebar: 4 | order: 51 5 | label: 51. Overloads 6 | --- 7 | 8 | 9 | Function overloads in TypeScript allow you to define multiple function signatures for a single function name, enabling you to define functions that can be called in multiple ways. Here's an example: 10 | 11 | ```typescript 12 | // Overloads 13 | function sayHi(name: string): string; 14 | function sayHi(names: string[]): string[]; 15 | 16 | // Implementation 17 | function sayHi(name: unknown): unknown { 18 | if (typeof name === 'string') { 19 | return `Hi, ${name}!`; 20 | } else if (Array.isArray(name)) { 21 | return name.map(name => `Hi, ${name}!`); 22 | } 23 | throw new Error('Invalid value'); 24 | } 25 | 26 | sayHi('xx'); // Valid 27 | sayHi(['aa', 'bb']); // Valid 28 | ``` 29 | 30 | Here's another example of using function overloads within a `class`: 31 | 32 | ```typescript 33 | class Greeter { 34 | message: string; 35 | 36 | constructor(message: string) { 37 | this.message = message; 38 | } 39 | 40 | // overload 41 | sayHi(name: string): string; 42 | sayHi(names: string[]): ReadonlyArray; 43 | 44 | // implementation 45 | sayHi(name: unknown): unknown { 46 | if (typeof name === 'string') { 47 | return `${this.message}, ${name}!`; 48 | } else if (Array.isArray(name)) { 49 | return name.map(name => `${this.message}, ${name}!`); 50 | } 51 | throw new Error('value is invalid'); 52 | } 53 | } 54 | console.log(new Greeter('Hello').sayHi('Simon')); 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /website/src/content/docs/book/predefined-conditional-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Predefined Conditional Types 3 | sidebar: 4 | order: 42 5 | label: 42. Predefined Conditional Types 6 | --- 7 | 8 | 9 | In TypeScript, Predefined Conditional Types are built-in conditional types provided by the language. They are designed to perform common type transformations based on the characteristics of a given type. 10 | 11 | `Exclude`: This type removes all the types from Type that are assignable to ExcludedType. 12 | 13 | `Extract`: This type extracts all the types from Union that are assignable to Type. 14 | 15 | `NonNullable`: This type removes null and undefined from Type. 16 | 17 | `ReturnType`: This type extracts the return type of a function Type. 18 | 19 | `Parameters`: This type extracts the parameter types of a function Type. 20 | 21 | `Required`: This type makes all properties in Type required. 22 | 23 | `Partial`: This type makes all properties in Type optional. 24 | 25 | `Readonly`: This type makes all properties in Type readonly. 26 | 27 | -------------------------------------------------------------------------------- /website/src/content/docs/book/readonly-properties.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Readonly Properties 3 | sidebar: 4 | order: 13 5 | label: 13. Readonly Properties 6 | --- 7 | 8 | 9 | Is it possible to prevent writing on a property by using the modifier `readonly`which makes sure that the property cannot be re-written but does not provide any guarantee of total immutability: 10 | 11 | ```typescript 12 | interface Y { 13 | readonly a: number; 14 | } 15 | 16 | type X = { 17 | readonly a: number; 18 | }; 19 | 20 | type J = Readonly<{ 21 | a: number; 22 | }>; 23 | 24 | type K = { 25 | readonly [index: number]: string; 26 | }; 27 | ``` 28 | 29 | -------------------------------------------------------------------------------- /website/src/content/docs/book/strictnullchecks.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: strictNullChecks 3 | sidebar: 4 | order: 18 5 | label: 18. strictNullChecks 6 | --- 7 | 8 | 9 | `strictNullChecks` is a TypeScript compiler option that enforces strict null checking. When this option is enabled, variables and parameters can only be assigned `null` or `undefined` if they have been explicitly declared to be of that type using the union type `null` | `undefined`. If a variable or parameter is not explicitly declared as nullable, TypeScript will generate an error to prevent potential runtime errors. 10 | 11 | -------------------------------------------------------------------------------- /website/src/content/docs/book/symbols.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Symbols 3 | sidebar: 4 | order: 58 5 | label: 58. Symbols 6 | --- 7 | 8 | 9 | Symbols are a primitive data type that represents an immutable value which is guaranteed to be globally unique throughout the lifetime of the program. 10 | 11 | Symbols can be used as keys for object properties and provide a way to create non-enumerable properties. 12 | 13 | ```typescript 14 | const key1: symbol = Symbol('key1'); 15 | const key2: symbol = Symbol('key2'); 16 | 17 | const obj = { 18 | [key1]: 'value 1', 19 | [key2]: 'value 2', 20 | }; 21 | 22 | console.log(obj[key1]); // value 1 23 | console.log(obj[key2]); // value 2 24 | ``` 25 | 26 | In WeakMaps and WeakSets, symbols are now permissible as keys. 27 | 28 | -------------------------------------------------------------------------------- /website/src/content/docs/book/template-union-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Template Union Types 3 | sidebar: 4 | order: 43 5 | label: 43. Template Union Types 6 | --- 7 | 8 | 9 | Template union types can be used to merge and manipulate text inside the type system for instance: 10 | 11 | ```typescript 12 | type Status = 'active' | 'inactive'; 13 | type Products = 'p1' | 'p2'; 14 | type ProductId = `id-${Products}-${Status}`; // "id-p1-active" | "id-p1-inactive" | "id-p2-active" | "id-p2-inactive" 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /website/src/content/docs/book/the-concise-typescript-book.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: The Concise TypeScript Book 3 | sidebar: 4 | order: 1 5 | label: 1. The Concise TypeScript Book 6 | --- 7 | 8 | 9 | The Concise TypeScript Book provides a comprehensive and succinct overview of TypeScript's capabilities. It offers clear explanations covering all aspects found in the latest version of the language, from its powerful type system to advanced features. Whether you're a beginner or an experienced developer, this book is an invaluable resource to enhance your understanding and proficiency in TypeScript. 10 | 11 | This book is completely Free and Open Source. 12 | 13 | If you found this TypeScript book valuable and wish to contribute, consider supporting my efforts via PayPal. Thanks! 14 | 15 | [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/donate/?business=QW82ZS956XLFY&no_recurring=0¤cy_code=EUR) 16 | 17 | -------------------------------------------------------------------------------- /website/src/content/docs/book/the-never-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: The never Type 3 | sidebar: 4 | order: 25 5 | label: 25. The never Type 6 | --- 7 | 8 | 9 | When a variable is narrowed to a type that cannot contain any values, the TypeScript compiler will infer that the variable must be of the `never` type. This is because The never Type represents a value that can never be produced. 10 | 11 | ```typescript 12 | const printValue = (val: string | number) => { 13 | if (typeof val === 'string') { 14 | console.log(val.toUpperCase()); 15 | } else if (typeof val === 'number') { 16 | console.log(val.toFixed(2)); 17 | } else { 18 | // val has type never here because it can never be anything other than a string or a number 19 | const neverVal: never = val; 20 | console.log(`Unexpected value: ${neverVal}`); 21 | } 22 | }; 23 | ``` 24 | 25 | -------------------------------------------------------------------------------- /website/src/content/docs/book/translations.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Translations 3 | sidebar: 4 | order: 2 5 | label: 2. Translations 6 | --- 7 | 8 | 9 | This book has been translated into several language versions, including: 10 | 11 | [Chinese](https://github.com/gibbok/typescript-book/blob/main/README-zh_CN.md) 12 | 13 | -------------------------------------------------------------------------------- /website/src/content/docs/book/triple-slash-directives.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Triple-Slash Directives 3 | sidebar: 4 | order: 59 5 | label: 59. Triple-Slash Directives 6 | --- 7 | 8 | 9 | Triple-slash directives are special comments that provide instructions to the compiler about how to process a file. These directives begin with three consecutive slashes (`///`) and are typically placed at the top of a TypeScript file and have no effects on the runtime behavior. 10 | 11 | Triple-slash directives are used to reference external dependencies, specify module loading behavior, enable/disable certain compiler features, and more. Few examples: 12 | 13 | Referencing a declaration file: 14 | 15 | 16 | ```typescript 17 | /// 18 | ``` 19 | 20 | Indicate the module format: 21 | 22 | 23 | ```typescript 24 | /// 25 | ``` 26 | 27 | Enable compiler options, in the following example strict mode: 28 | 29 | 30 | ```typescript 31 | /// 32 | ``` 33 | 34 | -------------------------------------------------------------------------------- /website/src/content/docs/book/tuple-type-anonymous.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Tuple Type (Anonymous) 3 | sidebar: 4 | order: 28 5 | label: 28. Tuple Type (Anonymous) 6 | --- 7 | 8 | 9 | A Tuple Type is a type that represents an array with a fixed number of elements and their corresponding types. A tuple type enforces a specific number of elements and their respective types in a fixed order. Tuple types are useful when you want to represent a collection of values with specific types, where the position of each element in the array has a specific meaning. 10 | 11 | ```typescript 12 | type Point = [number, number]; 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /website/src/content/docs/book/type-annotations.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Type Annotations 3 | sidebar: 4 | order: 11 5 | label: 11. Type Annotations 6 | --- 7 | 8 | 9 | On variables declared using `var`, `let` and `const`, it is possible to optionally add a type: 10 | 11 | ```typescript 12 | const x: number = 1; 13 | ``` 14 | 15 | TypeScript does a good job of inferring types, especially when simple one, so these declarations in most cases are not necessary. 16 | 17 | On functions is possible to add type annotations to parameters: 18 | 19 | ```typescript 20 | function sum(a: number, b: number) { 21 | return a + b; 22 | } 23 | ``` 24 | 25 | The following is an example using a anonymous functions (so called lambda function): 26 | 27 | ```typescript 28 | const sum = (a: number, b: number) => a + b; 29 | ``` 30 | 31 | These annotation can be avoided when a default value for a parameter is present: 32 | 33 | ```typescript 34 | const sum = (a = 10, b: number) => a + b; 35 | ``` 36 | 37 | Return type annotations can be added to functions: 38 | 39 | ```typescript 40 | const sum = (a = 10, b: number): number => a + b; 41 | ``` 42 | 43 | This is useful especially for more complex functions as writing expliciting the return type before an implementation can help better think about the function. 44 | 45 | Generally consider annotating type signatures but not the body local variables and add types always to object literals. 46 | 47 | -------------------------------------------------------------------------------- /website/src/content/docs/book/type-from-func-return.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Type from Func Return 3 | sidebar: 4 | order: 35 5 | label: 35. Type from Func Return 6 | --- 7 | 8 | 9 | Type from Func Return refers to the ability to automatically infer the return type of a function based on its implementation. This allows TypeScript to determine the type of the value returned by the function without explicit type annotations. 10 | 11 | ```typescript 12 | const add = (x: number, y: number) => x + y; // TypeScript can infer that the return type of the function is a number 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /website/src/content/docs/book/type-from-module.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Type from Module 3 | sidebar: 4 | order: 36 5 | label: 36. Type from Module 6 | --- 7 | 8 | 9 | Type from Module refers to the ability to use a module's exported values to automatically infer their types. When a module exports a value with a specific type, TypeScript can use that information to automatically infer the type of that value when it is imported into another module. 10 | 11 | 12 | ```typescript 13 | // calc.ts 14 | export const add = (x: number, y: number) => x + y; 15 | // index.ts 16 | import { add } from 'calc'; 17 | const r = add(1, 2); // r is number 18 | ``` 19 | 20 | -------------------------------------------------------------------------------- /website/src/content/docs/book/type-from-value.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Type from Value 3 | sidebar: 4 | order: 34 5 | label: 34. Type from Value 6 | --- 7 | 8 | 9 | Type from Value in TypeScript refers to the automatic inference of a type from a value or expression through type inference. 10 | 11 | ```typescript 12 | const x = 'x'; // TypeScript can automatically infer that the type of the message variable is string 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /website/src/content/docs/book/type-indexing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Type Indexing 3 | sidebar: 4 | order: 33 5 | label: 33. Type Indexing 6 | --- 7 | 8 | 9 | Type indexing refers to the ability to define types that can be indexed by a key that is not known in advance, using an index signature to specify the type for properties that are not explicitly declared. 10 | 11 | ```typescript 12 | type Dictionary = { 13 | [key: string]: T; 14 | }; 15 | const myDict: Dictionary = { a: 'a', b: 'b' }; 16 | console.log(myDict['a']); // Returns a 17 | ``` 18 | 19 | -------------------------------------------------------------------------------- /website/src/content/docs/book/type-predicates.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Type Predicates 3 | sidebar: 4 | order: 23 5 | label: 23. Type Predicates 6 | --- 7 | 8 | 9 | Type Predicates in TypeScript are functions that return a boolean value and are used to narrow the type of a variable to a more specific type. 10 | 11 | ```typescript 12 | const isString = (value: unknown): value is string => typeof value === 'string'; 13 | 14 | const foo = (bar: unknown) => { 15 | if (isString(bar)) { 16 | console.log(bar.toUpperCase()); 17 | } else { 18 | console.log('not a string'); 19 | } 20 | }; 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /website/src/content/docs/book/union-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Union Type 3 | sidebar: 4 | order: 31 5 | label: 31. Union Type 6 | --- 7 | 8 | 9 | A Union Type is a type that represents a value that can be one of several types. Union Types are denoted using the `|` symbol between each possible type. 10 | 11 | ```typescript 12 | let x: string | number; 13 | x = 'hello'; // Valid 14 | x = 123; // Valid 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /website/src/content/docs/book/unknown-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Unknown type 3 | sidebar: 4 | order: 45 5 | label: 45. Unknown type 6 | --- 7 | 8 | 9 | In TypeScript, the `unknown` type represents a value that is of an unknown type. Unlike `any` type, which allows for any type of value, `unknown` requires a type check or assertion before it can be used in a specific way so no operations are permitted on an `unknown` without first asserting or narrowing to a more specific type. 10 | 11 | The `unknown` type is only assignable to any type and the `unknown` type itself, it is a type-safe alternative to `any`. 12 | 13 | 14 | ```typescript 15 | let value: unknown; 16 | 17 | let value1: unknown = value; // Valid 18 | let value2: any = value; // Valid 19 | let value3: boolean = value; // Invalid 20 | let value4: number = value; // Invalid 21 | ``` 22 | 23 | ```typescript 24 | const add = (a: unknown, b: unknown): number | undefined => 25 | typeof a === 'number' && typeof b === 'number' ? a + b : undefined; 26 | console.log(add(1, 2)); // 3 27 | console.log(add('x', 2)); // undefined 28 | ``` 29 | 30 | -------------------------------------------------------------------------------- /website/src/content/docs/book/void-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Void type 3 | sidebar: 4 | order: 46 5 | label: 46. Void type 6 | --- 7 | 8 | 9 | The `void` type is used to indicate that a function does not return a value. 10 | 11 | ```typescript 12 | const sayHello = (): void => { 13 | console.log('Hello!'); 14 | }; 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /website/src/content/docs/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Typescript Book 3 | description: The Concise TypeScript Book 4 | template: splash 5 | hero: 6 | tagline: The Concise TypeScript Book provides a comprehensive and succinct overview of TypeScript's capabilities. It offers clear explanations covering all aspects found in the latest version of the language, from its powerful type system to advanced features. Whether you're a beginner or an experienced developer, this book is an invaluable resource to enhance your understanding and proficiency in TypeScript.

This book is completely Free and Open Source. 7 | actions: 8 | - text: Read now! 9 | link: /typescript-book/book/the-concise-typescript-book/ 10 | icon: right-arrow 11 | variant: primary 12 | - text: GitHub 13 | link: https://github.com/gibbok/typescript-book 14 | icon: github 15 | variant: secondary 16 | - text: X.com 17 | link: https://twitter.com/gibbok_coding 18 | icon: x.com 19 | variant: secondary 20 | --- 21 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/about-the-author.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 关于作者 3 | sidebar: 4 | order: 6 5 | label: 6. 关于作者 6 | --- 7 | 8 | 9 | Simone Poggiali 是一位经验丰富的高级前端开发人员,自 90 年代以来就热衷于编写专业级代码。在他的国际职业生涯中,他为从初创公司到大型组织的广泛客户提供了众多项目。HelloFresh、Siemens、O2 和 Leroy Merlin 等著名公司都受益于他的专业知识和奉献精神。 10 | 11 | 您可以通过以下平台联系 Simone Poggiali: 12 | 13 | * 领英: [https://www.linkedin.com/in/simone-poggiali](https://www.linkedin.com/in/simone-poggiali) 14 | * GitHub: [https://github.com/gibbok](https://github.com/gibbok) 15 | * X.com: [https://x.com/gibbok_coding](https://x.com/gibbok_coding) 16 | * 电子邮箱: gibbok.coding📧gmail.com 17 | 18 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/any-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 任意类型 3 | sidebar: 4 | order: 44 5 | label: 44. 任意类型 6 | --- 7 | 8 | 9 | `any` 类型是一种特殊类型(通用超类型),可用于表示任何类型的值(基元、对象、数组、函数、错误、符号)。它通常用于编译时未知值类型的情况,或者使用来自没有 TypeScript 类型的外部 API 或库的值时。 10 | 11 | 通过使用任何类型,您向 TypeScript 编译器指示值应该不受任何限制地表示。为了最大限度地提高代码中的类型安全性,请考虑以下事项: 12 | 13 | * 将 `any` 的使用限制在类型确实未知的特定情况下。 14 | * 不要从函数返回 `any` 类型,因为使用该函数会在代码中失去类型安全性,从而削弱类型安全性。 15 | * 如果您需要使编译器保持沉默,请使用 `@ts-ignore` 而不是 `any`。 16 | 17 | ```typescript 18 | let value: any; 19 | value = true; // 有效 20 | value = 7; // 有效 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/assignments.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 赋值 3 | sidebar: 4 | order: 21 5 | label: 21. 赋值 6 | --- 7 | 8 | 9 | 使用赋值缩小 TypeScript 是一种根据分配给变量的值来缩小变量类型的方法。当为变量分配值时,TypeScript 会根据分配的值推断其类型,并缩小变量的类型以匹配推断的类型。 10 | 11 | ```typescript 12 | let value: string | number; 13 | value = 'hello'; 14 | if (typeof value === 'string') { 15 | console.log(value.toUpperCase()); 16 | } 17 | value = 42; 18 | if (typeof value === 'number') { 19 | console.log(value.toFixed(2)); 20 | } 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/built-in-type-primitives.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 内置原始数据类型 3 | sidebar: 4 | order: 49 5 | label: 49. 内置原始数据类型 6 | --- 7 | 8 | 9 | TypeScript 有几个内置的原属数据类型,可用于定义变量、函数参数和返回类型: 10 | 11 | `number`: 表示数值,包括整数和浮点数。 12 | `string`: 代表文本数据。 13 | `boolean`: 代表逻辑值,可以是 true 或 false。 14 | `null`: 表示没有值。 15 | `undefined`: 表示尚未赋值或未定义的值。 16 | `symbol`: 代表唯一标识符。符号通常用作对象属性的键。 17 | `bigint`: 表示任意精度整数。 18 | `any`: 代表动态或未知类型。any 类型的变量可以保存任何类型的值,并且它们绕过类型检查。 19 | `void`: 表示不存在任何类型。它通常用作不返回值的函数的返回类型。 20 | `never`: 表示从未出现过的值的类型。它通常用作引发错误或进入无限循环的函数的返回类型。 21 | 22 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/common-built-in-js-objects.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 常见的内置JS对象 3 | sidebar: 4 | order: 50 5 | label: 50. 常见的内置JS对象 6 | --- 7 | 8 | 9 | TypeScript 是 JavaScript 的超集,它包含所有常用的内置 JavaScript 对象。您可以在 Mozilla 开发者网络 (MDN) 文档网站上找到这些对象的详细列表: 10 | [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects) 11 | 12 | 以下是一些常用的内置 JavaScript 对象的列表: 13 | 14 | * Function 15 | * Object 16 | * Boolean 17 | * Error 18 | * Number 19 | * BigInt 20 | * Math 21 | * Date 22 | * String 23 | * RegExp 24 | * Array 25 | * Map 26 | * Set 27 | * Promise 28 | * Intl 29 | 30 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/conditional-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 条件类型 3 | sidebar: 4 | order: 39 5 | label: 39. 条件类型 6 | --- 7 | 8 | 9 | 条件类型是一种创建依赖于条件的类型的方法,其中要创建的类型是根据条件的结果确定的。它们是使用 `extends` 关键字和三元运算符来定义的,以便有条件地在两种类型之间进行选择。 10 | 11 | ```typescript 12 | type IsArray = T extends any[] ? true : false; 13 | 14 | const myArray = [1, 2, 3]; 15 | const myNumber = 42; 16 | 17 | type IsMyArrayAnArray = IsArray; // true 类型 18 | type IsMyNumberAnArray = IsArray; // false 类型 19 | ``` 20 | 21 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/control-flow-analysis.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 控制流分析 3 | sidebar: 4 | order: 22 5 | label: 22. 控制流分析 6 | --- 7 | 8 | 9 | TypeScript 中的控制流分析是一种静态分析代码流以推断变量类型的方法,允许编译器根据分析结果根据需要缩小这些变量的类型。 10 | 11 | 在 TypeScript 4.4 之前,代码流分析仅适用于 if 语句中的代码,但从 TypeScript 4.4 开始,它还可以应用于条件表达式和通过 const 变量间接引用的判别式属性访问。 12 | 13 | 例如: 14 | 15 | ```typescript 16 | const f1 = (x: unknown) => { 17 | const isString = typeof x === 'string'; 18 | if (isString) { 19 | x.length; 20 | } 21 | }; 22 | 23 | const f2 = ( 24 | obj: { kind: 'foo'; foo: string } | { kind: 'bar'; bar: number } 25 | ) => { 26 | const isFoo = obj.kind === 'foo'; 27 | if (isFoo) { 28 | obj.foo; 29 | } else { 30 | obj.bar; 31 | } 32 | }; 33 | ``` 34 | 35 | 一些未发生缩小的示例: 36 | 37 | 38 | ```typescript 39 | const f1 = (x: unknown) => { 40 | let isString = typeof x === 'string'; 41 | if (isString) { 42 | x.length; // 错误, 没有缩小,因为 isString 不是常量 43 | } 44 | }; 45 | 46 | const f6 = ( 47 | obj: { kind: 'foo'; foo: string } | { kind: 'bar'; bar: number } 48 | ) => { 49 | const isFoo = obj.kind === 'foo'; 50 | obj = obj; 51 | if (isFoo) { 52 | obj.foo; // 错误, 没有缩小,因为 obj 在函数体中被赋值 53 | } 54 | }; 55 | ``` 56 | 57 | 注意: 在条件表达式中最多分析五个间接级别。 58 | 59 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/differences-between-type-and-interface.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 类型和接口之间的差异 3 | sidebar: 4 | order: 53 5 | label: 53. 类型和接口之间的差异 6 | --- 7 | 8 | 9 | 声明合并(增强): 10 | 11 | 接口支持声明合并,这意味着您可以定义多个具有相同名称的接口,TypeScript 会将它们合并为具有组合属性和方法的单个接口。 另一方面,类型不支持声明合并。 当您想要添加额外的功能或自定义现有类型而不修改原始定义或修补丢失或不正确的类型时,这可能会很有帮助。 12 | 13 | ```typescript 14 | interface A { 15 | x: string; 16 | } 17 | interface A { 18 | y: string; 19 | } 20 | const j: A = { 21 | x: 'xx', 22 | y: 'yy', 23 | }; 24 | ``` 25 | 26 | 扩展其他类型/接口: 27 | 28 | 类型和接口都可以扩展其他类型/接口,但语法不同。 对于接口,您可以使用“extends”关键字从其他接口继承属性和方法。 但是,接口无法扩展像联合类型这样的复杂类型。 29 | 30 | ```typescript 31 | interface A { 32 | x: string; 33 | y: number; 34 | } 35 | interface B extends A { 36 | z: string; 37 | } 38 | const car: B = { 39 | x: 'x', 40 | y: 123, 41 | z: 'z', 42 | }; 43 | ``` 44 | 45 | 对于类型,您可以使用 & 运算符将多个类型合并为单个类型(交集)。 46 | 47 | ```typescript 48 | interface A { 49 | x: string; 50 | y: number; 51 | } 52 | 53 | type B = A & { 54 | j: string; 55 | }; 56 | 57 | const c: B = { 58 | x: 'x', 59 | y: 123, 60 | j: 'j', 61 | }; 62 | ``` 63 | 64 | 并集和交集类型: 65 | 66 | 在定义并集和交集类型时,类型更加灵活。 通过“type”关键字,您可以使用“|”运算符轻松创建联合类型,并使用“&”运算符创建交集类型。 虽然接口也可以间接表示联合类型,但它们没有对交集类型的内置支持。 67 | 68 | ```typescript 69 | type Department = 'dep-x' | 'dep-y'; // 并集 70 | 71 | type Person = { 72 | name: string; 73 | age: number; 74 | }; 75 | 76 | type Employee = { 77 | id: number; 78 | department: Department; 79 | }; 80 | 81 | type EmployeeInfo = Person & Employee; // 交集 82 | ``` 83 | 84 | 接口示例: 85 | 86 | ```typescript 87 | interface A { 88 | x: 'x'; 89 | } 90 | interface B { 91 | y: 'y'; 92 | } 93 | 94 | type C = A | B; // 接口的并集 95 | ``` 96 | 97 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/discriminated-unions.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 可区分联合 3 | sidebar: 4 | order: 24 5 | label: 24. 可区分联合 6 | --- 7 | 8 | 9 | TypeScript 中的可区分联合是一种联合类型,它使用称为判别式的公共属性来缩小联合的可能类型集。 10 | 11 | ```typescript 12 | type Square = { 13 | kind: 'square'; // 判别式 14 | size: number; 15 | }; 16 | 17 | type Circle = { 18 | kind: 'circle'; // 判别式 19 | radius: number; 20 | }; 21 | 22 | type Shape = Square | Circle; 23 | 24 | const area = (shape: Shape) => { 25 | switch (shape.kind) { 26 | case 'square': 27 | return Math.pow(shape.size, 2); 28 | case 'circle': 29 | return Math.PI * Math.pow(shape.radius, 2); 30 | } 31 | }; 32 | 33 | const square: Square = { kind: 'square', size: 5 }; 34 | const circle: Circle = { kind: 'circle', radius: 2 }; 35 | 36 | console.log(area(square)); // 25 37 | console.log(area(circle)); // 12.566370614359172 38 | ``` 39 | 40 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/distributive-conditional-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 分配条件类型 3 | sidebar: 4 | order: 40 5 | label: 40. 分配条件类型 6 | --- 7 | 8 | 9 | 分布式条件类型是一种功能,通过单独对联合的每个成员应用转换,允许类型分布在类型的联合上。当使用映射类型或高阶类型时,这尤其有用。 10 | 11 | ```typescript 12 | type Nullable = T extends any ? T | null : never; 13 | type NumberOrBool = number | boolean; 14 | type NullableNumberOrBool = Nullable; // number | boolean | null 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/downloads-and-website.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 下载和网站 3 | sidebar: 4 | order: 3 5 | label: 3. 下载和网站 6 | --- 7 | 8 | 9 | 您还可以下载 Epub 版本: 10 | 11 | [https://github.com/gibbok/typescript-book/tree/main/downloads](https://github.com/gibbok/typescript-book/tree/main/downloads) 12 | 13 | 在线版本可在以下位置获得: 14 | 15 | [https://gibbok.github.io/typescript-book](https://gibbok.github.io/typescript-book) 16 | 17 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/erased-structural-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 擦除的结构类型 3 | sidebar: 4 | order: 56 5 | label: 56. 擦除的结构类型 6 | --- 7 | 8 | 9 | 在 TypeScript 中,对象不必匹配特定的、精确的类型。例如,如果我们创建一个满足接口要求的对象,我们就可以在需要该接口的地方使用该对象,即使它们之间没有显式连接。例子: 10 | 11 | ```typescript 12 | type NameProp1 = { 13 | prop1: string; 14 | }; 15 | 16 | function log(x: NameProp1) { 17 | console.log(x.prop1); 18 | } 19 | 20 | const obj = { 21 | prop2: 123, 22 | prop1: 'Origin', 23 | }; 24 | 25 | log(obj); // 有效 26 | ``` 27 | 28 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/exhaustiveness-checking.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 详尽性检查 3 | sidebar: 4 | order: 26 5 | label: 26. 详尽性检查 6 | --- 7 | 8 | 9 | 详尽性检查是 TypeScript 中的一项功能,可确保在 `switch` 语句或 `if` 语句中处理可区分联合的所有可能情况。 10 | 11 | ```typescript 12 | type Direction = 'up' | 'down'; 13 | 14 | const move = (direction: Direction) => { 15 | switch (direction) { 16 | case 'up': 17 | console.log('Moving up'); 18 | break; 19 | case 'down': 20 | console.log('Moving down'); 21 | break; 22 | default: 23 | const exhaustiveCheck: never = direction; 24 | console.log(exhaustiveCheck); // 这行永远不会被执行 25 | } 26 | }; 27 | ``` 28 | 29 | 该 `never` 类型用于确保默认情况是详尽的,并且如果将新值添加到 Direction 类型而未在 switch 语句中进行处理,则 TypeScript 将引发错误。 30 | 31 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/extending-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 扩展类型 3 | sidebar: 4 | order: 15 5 | label: 15. 扩展类型 6 | --- 7 | 8 | 9 | 可以扩展 `interface`(从另一种类型复制成员): 10 | 11 | ```typescript 12 | interface X { 13 | a: string; 14 | } 15 | interface Y extends X { 16 | b: string; 17 | } 18 | ``` 19 | 20 | 还可以从多种 `interface` 进行扩展: 21 | 22 | ```typescript 23 | interface A { 24 | a: string; 25 | } 26 | interface B { 27 | b: string; 28 | } 29 | interface Y extends A, B { 30 | y: string; 31 | } 32 | ``` 33 | 34 | 该 `extends` 关键字仅适用于 `interface`,因为 `type` 使用交集: 35 | 36 | ```typescript 37 | type A = { 38 | a: number; 39 | }; 40 | type B = { 41 | b: number; 42 | }; 43 | type C = A & B; 44 | ``` 45 | 46 | 可以使用 `interface` 来扩展类 `type`,但反之则不然: 47 | 48 | ```typescript 49 | type A = { 50 | a: string; 51 | }; 52 | interface B extends A { 53 | b: string; 54 | } 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/fixed-length-tuple.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 固定长度元组 3 | sidebar: 4 | order: 30 5 | label: 30. 固定长度元组 6 | --- 7 | 8 | 9 | 固定长度元组是一种特定类型的元组,它强制执行特定类型的固定数量的元素,并且一旦定义元组就不允许对其长度进行任何修改。 10 | 11 | 当您需要表示具有特定数量的元素和特定类型的值的集合,并且您希望确保元组的长度和类型不会无意中更改时,固定长度元组非常有用。 12 | 13 | 14 | ```typescript 15 | const x = [10, 'hello'] as const; 16 | x.push(2); // 错误 17 | ``` 18 | 19 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/generics.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 泛型 3 | sidebar: 4 | order: 55 5 | label: 55. 泛型 6 | --- 7 | 8 | 9 | 泛型允许您创建可与多种类型一起使用的可重用组件和函数。使用泛型,您可以参数化类型、函数和接口,从而允许它们对不同类型进行操作,而无需事先显式指定它们。 10 | 11 | 泛型允许您使代码更加灵活和可重用。 12 | 13 | ### 泛型类型 14 | 15 | 要定义泛型类型,可以使用尖括号 (`<>`) 来指定类型参数,例如: 16 | 17 | ```typescript 18 | function identity(arg: T): T { 19 | return arg; 20 | } 21 | const a = identity('x'); 22 | const b = identity(123); 23 | 24 | const getLen = (data: ReadonlyArray) => data.length; 25 | const len = getLen([1, 2, 3]); 26 | ``` 27 | 28 | ### 泛型类 29 | 30 | 泛型也可以应用于类,这样它们就可以通过使用类型参数来处理多种类型。这对于创建可重用的类定义非常有用,这些定义可以在保持类型安全的同时对不同的数据类型进行操作。 31 | 32 | ```typescript 33 | class Container { 34 | private item: T; 35 | 36 | constructor(item: T) { 37 | this.item = item; 38 | } 39 | 40 | getItem(): T { 41 | return this.item; 42 | } 43 | } 44 | 45 | const numberContainer = new Container(123); 46 | console.log(numberContainer.getItem()); // 123 47 | 48 | const stringContainer = new Container('hello'); 49 | console.log(stringContainer.getItem()); // hello 50 | ``` 51 | 52 | ### 泛型约束 53 | 54 | 可以使用关键字 `extends` 后跟类型参数必须满足的类型或接口来约束泛型参数。 55 | 56 | 在下面的示例中,T 必须正确包含 `length` 才能有效: 57 | 58 | 59 | ```typescript 60 | const printLen = (value: T): void => { 61 | console.log(value.length); 62 | }; 63 | 64 | printLen('Hello'); // 5 65 | printLen([1, 2, 3]); // 3 66 | printLen({ length: 10 }); // 10 67 | printLen(123); // 无效 68 | ``` 69 | 70 | 3.4 RC 版中引入的泛型的一个有趣功能是高阶函数类型推断,它引入了传播泛型类型参数: 71 | 72 | ```typescript 73 | declare function pipe
( 74 | ab: (...args: A) => B, 75 | bc: (b: B) => C 76 | ): (...args: A) => C; 77 | 78 | declare function list(a: T): T[]; 79 | declare function box(x: V): { value: V }; 80 | 81 | const listBox = pipe(list, box); // (a: T) => { value: T[] } 82 | const boxList = pipe(box, list); // (x: V) => { value: V }[] 83 | ``` 84 | 85 | 此功能允许更轻松地键入安全的无点风格编程,这在函数式编程中很常见。 86 | 87 | ### 泛型上下文缩小 88 | 89 | 泛型上下文缩小是 TypeScript 中的机制,允许编译器根据使用泛型参数的上下文来缩小泛型参数的类型,在条件语句中使用泛型类型时非常有用: 90 | 91 | ```typescript 92 | function process(value: T): void { 93 | if (typeof value === 'string') { 94 | // Value 的类型被缩小到 'string' 类型 95 | console.log(value.length); 96 | } else if (typeof value === 'number') { 97 | // Value 的类型被缩小到 'number' 类型 98 | console.log(value.toFixed(2)); 99 | } 100 | } 101 | 102 | process('hello'); // 5 103 | process(3.14159); // 3.14 104 | ``` 105 | 106 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/index-signatures.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 索引签名 3 | sidebar: 4 | order: 14 5 | label: 14. 索引签名 6 | --- 7 | 8 | 9 | 在 TypeScript 中,我们可以使用 `string` 、`number` 和 `symbol` 作为索引签名: 10 | 11 | ```typescript 12 | type K = { 13 | [name: string | number]: string; 14 | }; 15 | const k: K = { x: 'x', 1: 'b' }; 16 | console.log(k['x']); 17 | console.log(k[1]); 18 | console.log(k['1']); // 同 k[1] 的结果相同 19 | ``` 20 | 21 | 请注意,JavaScript 会自动将 `number` 的索引转换相同值的 'string'索引, 比如 `k[1]` 和 `k["1"]` 返回相同值。 22 | 23 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/infer-type-inference-in-conditional-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: infer 条件类型中的类型推断 3 | sidebar: 4 | order: 41 5 | label: 41. infer 条件类型中的类型推断 6 | --- 7 | 8 | 9 | `infer` 关键字在条件类型中使用,用于从依赖于泛型参数的类型中推断(提取)泛型参数的类型。这允许您编写更灵活且可重用的类型定义。 10 | 11 | ```typescript 12 | type ElementType = T extends (infer U)[] ? U : never; 13 | type Numbers = ElementType; // number 14 | type Strings = ElementType; // string 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/interface-and-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 接口及类型 3 | sidebar: 4 | order: 48 5 | label: 48. 接口及类型 6 | --- 7 | 8 | 9 | ### 通用语法 10 | 11 | 在 TypeScript 中,接口定义对象的结构,指定对象必须具有的属性或方法的名称和类型。在 TypeScript 中定义接口的常用语法如下: 12 | 13 | 14 | ```typescript 15 | interface InterfaceName { 16 | property1: Type1; 17 | // ... 18 | method1(arg1: ArgType1, arg2: ArgType2): ReturnType; 19 | // ... 20 | } 21 | ``` 22 | 23 | 类型定义也类似: 24 | 25 | 26 | ```typescript 27 | type TypeName = { 28 | property1: Type1; 29 | // ... 30 | method1(arg1: ArgType1, arg2: ArgType2): ReturnType; 31 | // ... 32 | }; 33 | ``` 34 | 35 | `interface InterfaceName` 或者 `type TypeName`: 定义接口的名称。 36 | `property1`: `Type1`: 指定接口的属性及其相应的类型。可以定义多个属性,每个属性用分号分隔。 37 | `method1(arg1: ArgType1, arg2: ArgType2): ReturnType;`: 指定接口的方法。方法用其名称进行定义,后跟括号中的参数列表和返回类型。可以定义多个方法,每个方法用分号分隔。 38 | 39 | 接口示例: 40 | 41 | ```typescript 42 | interface Person { 43 | name: string; 44 | age: number; 45 | greet(): void; 46 | } 47 | ``` 48 | 49 | 类型示例: 50 | 51 | ```typescript 52 | type TypeName = { 53 | property1: string; 54 | method1(arg1: string, arg2: string): string; 55 | }; 56 | ``` 57 | 58 | 在 TypeScript 中,类型用于定义数据的形状并强制执行类型检查。在 TypeScript 中定义类型有几种常见的语法,具体取决于具体的用例。这里有些例子: 59 | 60 | ### 基本类型 61 | 62 | ```typescript 63 | let myNumber: number = 123; // 数字类型 64 | let myBoolean: boolean = true; // 布尔类型 65 | let myArray: string[] = ['a', 'b']; // 字符串数组 66 | let myTuple: [string, number] = ['a', 123]; // 元组 67 | ``` 68 | 69 | ### 对象和接口 70 | 71 | ```typescript 72 | const x: { name: string; age: number } = { name: 'Simon', age: 7 }; 73 | ``` 74 | 75 | ### 并集和交集类型 76 | 77 | ```typescript 78 | type MyType = string | number; // 并集 79 | let myUnion: MyType = 'hello'; // 可以是字符串 80 | myUnion = 123; // 或者是一个数字 81 | 82 | type TypeA = { name: string }; 83 | type TypeB = { age: number }; 84 | type CombinedType = TypeA & TypeB; // 交集 85 | let myCombined: CombinedType = { name: 'John', age: 25 }; // 对象同时有name和age属性 86 | ``` 87 | 88 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/intersection-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 交集类型 3 | sidebar: 4 | order: 32 5 | label: 32. 交集类型 6 | --- 7 | 8 | 9 | 交集类型是表示具有两种或多种类型的所有属性的值的类型。交叉类型在每种类型之间使用 & 符号表示。 10 | 11 | ```typescript 12 | type X = { 13 | a: string; 14 | }; 15 | 16 | type Y = { 17 | b: string; 18 | }; 19 | 20 | type J = X & Y; // 交集 21 | 22 | const j: J = { 23 | a: 'a', 24 | b: 'b', 25 | }; 26 | ``` 27 | 28 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 介绍 3 | sidebar: 4 | order: 5 5 | label: 5. 介绍 6 | --- 7 | 8 | 9 | 欢迎来到简洁的TypeScript之书!本指南为您提供有效 TypeScript 开发的基本知识和实践技能。发现编写干净、健壮的代码的关键概念和技术。无论您是初学者还是经验丰富的开发人员,本书都可以作为在项目中利用 TypeScript 强大功能的综合指南和便捷参考。 10 | 11 | 本书涵盖了 TypeScript 5.2。 12 | 13 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/literal-inference.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 字面量推断 3 | sidebar: 4 | order: 17 5 | label: 17. 字面量推断 6 | --- 7 | 8 | 9 | 字面量推断是 TypeScript 中的一项功能,允许根据变量或参数的值推断其类型。 10 | 11 | 在下面的示例中,我们可以看到 TypeScript 认为x文字类型是因为该值以后不能随时更改,而y被推断为字符串,因为它以后可以随时修改。 12 | 13 | ```typescript 14 | const x = 'x'; // x 为字面量类型, 因为值不能改变 15 | let y = 'y'; // string, 我们能改变这个值 16 | ``` 17 | 18 | 在下面的示例中,我们可以看到 `o.x` 被推断为 `string`(而不是字面量的a),因为 TypeScript 认为该值可以在以后随时更改。 19 | 20 | 21 | ```typescript 22 | type X = 'a' | 'b'; 23 | 24 | let o = { 25 | x: 'a', // 这是一个更宽的 string 26 | }; 27 | 28 | const fn = (x: X) => `${x}-foo`; 29 | 30 | console.log(fn(o.x)); // 'string' 类型的参数不能赋值给 'X' 类型的参数 31 | ``` 32 | 33 | 正如你所看到的代码在传递 `o.x` 给 `fn` 作为一个狭窄类型时,抛出了一个错误。 34 | 35 | 我们能通过使用 `const` 或者 `X` 来借助类型推断解决这个问题: 36 | 37 | 38 | ```typescript 39 | let o = { 40 | x: 'a' as const, 41 | }; 42 | ``` 43 | 44 | or: 45 | 46 | 47 | ```typescript 48 | let o = { 49 | x: 'a' as X, 50 | }; 51 | ``` 52 | 53 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/literal-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 字面量类型 3 | sidebar: 4 | order: 16 5 | label: 16. 字面量类型 6 | --- 7 | 8 | 9 | 文字类型是来自集体类型的单个元素集,它定义了一个非常精确的值,即 JavaScript 原始数据。 10 | 11 | TypeScript 中的文字类型是数字、字符串和布尔值。 12 | 13 | 示例如下: 14 | 15 | ```typescript 16 | const a = 'a'; // 字符串字面量类型 17 | const b = 1; // 数字字面量类型 18 | const c = true; // 布尔字面量类型 19 | ``` 20 | 21 | 字符串、数字和布尔字面量类型用于联合、类型保护和类型别名。在下面的示例中,您可以看到类型别名联合,O可以是指定的唯一值,而不是任何其他字符串: 22 | 23 | ```typescript 24 | type O = 'a' | 'b' | 'c'; 25 | ``` 26 | 27 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/mapped-type-modifiers.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 映射类型修饰符 3 | sidebar: 4 | order: 38 5 | label: 38. 映射类型修饰符 6 | --- 7 | 8 | 9 | TypeScript 中的映射类型修饰符支持对现有类型中的属性进行转换: 10 | 11 | * `readonly` 或 `+readonly`:这会将映射类型中的属性呈现为只读。 12 | * `-readonly`:这允许映射类型中的属性是可变的。 13 | * `?`:这将映射类型中的属性指定为可选。 14 | 15 | 例子: 16 | 17 | ```typescript 18 | type ReadOnly = { readonly [P in keyof T]: T[P] }; // 所有属性标记为只读 19 | 20 | type Mutable = { -readonly [P in keyof T]: T[P] }; // 所有标记为可变的属性 21 | 22 | type MyPartial = { [P in keyof T]?: T[P] }; // 所有标记为可选的属性 23 | ```` 24 | 25 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/mapped-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 映射类型 3 | sidebar: 4 | order: 37 5 | label: 37. 映射类型 6 | --- 7 | 8 | 9 | TypeScript 中的映射类型允许您通过使用映射函数转换每个属性来基于现有类型创建新类型。通过映射现有类型,您可以创建以不同格式表示相同信息的新类型。要创建映射类型,您可以使用运算符访问现有类型的属性 `keyof` ,然后更改它们以生成新类型。在以下示例中: 10 | 11 | ```typescript 12 | type MyMappedType = { 13 | [P in keyof T]: T[P][]; 14 | }; 15 | type MyType = { 16 | foo: string; 17 | bar: number; 18 | }; 19 | type MyNewType = MyMappedType; 20 | const x: MyNewType = { 21 | foo: ['hello', 'world'], 22 | bar: [1, 2, 3], 23 | }; 24 | ``` 25 | 26 | 我们定义 MyMappedType 来映射 T 的属性,创建一个新类型,其中每个属性都是其原始类型的数组。使用它,我们创建 MyNewType 来表示与 MyType 相同的信息,但每个属性都是一个数组。 27 | 28 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/merging-and-extension.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 合并与扩展 3 | sidebar: 4 | order: 52 5 | label: 52. 合并与扩展 6 | --- 7 | 8 | 9 | 合并和扩展是指与使用类型和接口相关的两个不同概念。 10 | 11 | 合并允许您将多个同名声明合并到一个定义中,例如,当您多次定义同名接口时: 12 | 13 | ```typescript 14 | interface X { 15 | a: string; 16 | } 17 | 18 | interface X { 19 | b: number; 20 | } 21 | 22 | const person: X = { 23 | a: 'a', 24 | b: 7, 25 | }; 26 | ``` 27 | 28 | 扩展是指扩展或继承现有类型或接口以创建新类型或接口的能力。它是一种向现有类型添加附加属性或方法而不修改其原始定义的机制。例子: 29 | 30 | ```typescript 31 | interface Animal { 32 | name: string; 33 | eat(): void; 34 | } 35 | 36 | interface Bird extends Animal { 37 | sing(): void; 38 | } 39 | 40 | const dog: Bird = { 41 | name: 'Bird 1', 42 | eat() { 43 | console.log('Eating'); 44 | }, 45 | sing() { 46 | console.log('Singing'); 47 | }, 48 | }; 49 | ``` 50 | 51 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/named-tuple-type-labeled.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 命名元组类型(已标记) 3 | sidebar: 4 | order: 29 5 | label: 29. 命名元组类型(已标记) 6 | --- 7 | 8 | 9 | 元组类型可以包含每个元素的可选标签或名称。 这些标签用于提高可读性和工具帮助,不会影响您可以使用它们执行的操作。 10 | 11 | ```typescript 12 | type T = string; 13 | type Tuple1 = [T, T]; 14 | type Tuple2 = [a: T, b: T]; 15 | type Tuple3 = [a: T, T]; // 命名元组加匿名元组 16 | ``` 17 | 18 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/namespacing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 命名空间 3 | sidebar: 4 | order: 57 5 | label: 57. 命名空间 6 | --- 7 | 8 | 9 | 在 TypeScript 中,命名空间用于将代码组织到逻辑容器中,防止命名冲突并提供一种将相关代码分组在一起的方法。使用关键字 `export` 允许在"外部"模块中访问名称空间。 10 | 11 | ```typescript 12 | export namespace MyNamespace { 13 | export interface MyInterface1 { 14 | prop1: boolean; 15 | } 16 | export interface MyInterface2 { 17 | prop2: string; 18 | } 19 | } 20 | 21 | const a: MyNamespace.MyInterface1 = { 22 | prop1: true, 23 | }; 24 | ``` 25 | 26 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/narrowing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 缩小范围 3 | sidebar: 4 | order: 20 5 | label: 20. 缩小范围 6 | --- 7 | 8 | 9 | TypeScript 缩小范围是细化条件块内变量类型的过程。这在使用联合类型时很有用,其中一个变量可以有多个类型。 10 | 11 | TypeScript 可识别多种缩小类型范围的方法: 12 | 13 | ### typeof 类型保护 14 | 15 | typeof 类型保护是 TypeScript 中的一种特定类型保护,它根据变量的内置 JavaScript 类型检查变量的类型。 16 | 17 | ```typescript 18 | const fn = (x: number | string) => { 19 | if (typeof x === 'number') { 20 | return x + 1; // x 是数字 21 | } 22 | return -1; 23 | }; 24 | ``` 25 | 26 | ### 真实性缩小 27 | 28 | TypeScript 中的真实性缩小是通过检查变量是真还是假来相应地缩小其类型来实现的。 29 | 30 | ```typescript 31 | const toUpperCase = (name: string | null) => { 32 | if (name) { 33 | return name.toUpperCase(); 34 | } else { 35 | return null; 36 | } 37 | }; 38 | ``` 39 | 40 | ### 相等缩小 41 | 42 | TypeScript 中的相等缩小通过检查变量是否等于特定值来相应缩小其类型。 43 | 44 | 它与`switch`语句和等号运算符(例如`===`、`!==`、`==`和`!=`)结合使用来缩小类型范围。 45 | 46 | ```typescript 47 | const checkStatus = (status: 'success' | 'error') => { 48 | switch (status) { 49 | case 'success': 50 | return true 51 | case 'error': 52 | return null 53 | } 54 | }; 55 | ``` 56 | 57 | ### In运算符缩小 58 | 59 | TypeScript 中的 `in` 运算符缩小范围是一种根据变量类型中是否存在属性来缩小变量类型的方法。 60 | 61 | ```typescript 62 | type Dog = { 63 | name: string; 64 | breed: string; 65 | }; 66 | 67 | type Cat = { 68 | name: string; 69 | likesCream: boolean; 70 | }; 71 | 72 | const getAnimalType = (pet: Dog | Cat) => { 73 | if ('breed' in pet) { 74 | return 'dog'; 75 | } else { 76 | return 'cat'; 77 | } 78 | }; 79 | ``` 80 | 81 | ### instanceof 缩小 82 | 83 | TypeScript 中的 `instanceof` 运算符缩小是一种根据变量的构造函数缩小变量类型的方法,方法是检查对象是否是某个类或接口的实例。 84 | 85 | ```typescript 86 | class Square { 87 | constructor(public width: number) {} 88 | } 89 | class Rectangle { 90 | constructor( 91 | public width: number, 92 | public height: number 93 | ) {} 94 | } 95 | function area(shape: Square | Rectangle) { 96 | if (shape instanceof Square) { 97 | return shape.width * shape.width; 98 | } else { 99 | return shape.width * shape.height; 100 | } 101 | } 102 | const square = new Square(5); 103 | const rectangle = new Rectangle(5, 10); 104 | console.log(area(square)); // 25 105 | console.log(area(rectangle)); // 50 106 | ``` 107 | 108 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/never-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Never类型 3 | sidebar: 4 | order: 47 5 | label: 47. Never类型 6 | --- 7 | 8 | 9 | `never` 类型表示从未出现过的值。它用于表示从不返回或抛出错误的函数或表达式。 10 | 11 | 例如无限循环: 12 | 13 | ```typescript 14 | const infiniteLoop = (): never => { 15 | while (true) { 16 | // 做点什么 17 | } 18 | }; 19 | ``` 20 | 21 | 抛出错误: 22 | 23 | ```typescript 24 | const throwError = (message: string): never => { 25 | throw new Error(message); 26 | }; 27 | ``` 28 | 29 | `never` 类型对于确保类型安全和捕获代码中的潜在错误很有用。当与其他类型和控制流语句结合使用时,它可以帮助 TypeScript 分析和推断更精确的类型,例如: 30 | 31 | ```typescript 32 | type Direction = 'up' | 'down'; 33 | const move = (direction: Direction): void => { 34 | switch (direction) { 35 | case 'up': 36 | // 向上移动 37 | break; 38 | case 'down': 39 | // 向下移动 40 | break; 41 | default: 42 | const exhaustiveCheck: never = direction; 43 | throw new Error(`Unhandled direction: ${exhaustiveCheck}`); 44 | } 45 | }; 46 | ``` 47 | 48 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/object-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 对象类型 3 | sidebar: 4 | order: 27 5 | label: 27. 对象类型 6 | --- 7 | 8 | 9 | 在 TypeScript 中,对象类型描述对象的形状。它们指定对象属性的名称和类型,以及这些属性是必需的还是可选的。 10 | 11 | 在 TypeScript 中,您可以通过两种主要方式定义对象类型: 12 | 13 | 通过指定对象属性的名称、类型和可选性来定义对象的形状的接口。 14 | 15 | ```typescript 16 | interface User { 17 | name: string; 18 | age: number; 19 | email?: string; 20 | } 21 | ``` 22 | 23 | 类型别名与接口类似,定义了对象的形状。但是,它还可以基于现有类型或现有类型的组合创建新的自定义类型。这包括定义联合类型、交集类型和其他复杂类型。 24 | 25 | ```typescript 26 | type Point = { 27 | x: number; 28 | y: number; 29 | }; 30 | ``` 31 | 32 | 也可以匿名定义类型: 33 | 34 | ```typescript 35 | const sum = (x: { a: number; b: number }) => x.a + x.b; 36 | console.log(sum({ a: 5, b: 1 })); 37 | ``` 38 | 39 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/optional-properties.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 可选属性 3 | sidebar: 4 | order: 12 5 | label: 12. 可选属性 6 | --- 7 | 8 | 9 | 对象可以通过在属性名称末尾添加问号 `?` 来指定可选属性: 10 | 11 | ```typescript 12 | type X = { 13 | a: number; 14 | b?: number; // 可选的 15 | }; 16 | ``` 17 | 18 | 当属性是可选的时,可以指定默认值 19 | 20 | ```typescript 21 | type X = { 22 | a: number; 23 | b?: number; 24 | }; 25 | const x = ({ a, b = 100 }: X) => a + b; 26 | ``` 27 | 28 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/overloads.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 重载 3 | sidebar: 4 | order: 51 5 | label: 51. 重载 6 | --- 7 | 8 | 9 | TypeScript 中的函数重载允许您为单个函数名称定义多个函数签名,从而使您能够定义可以多种方式调用的函数。这是一个例子: 10 | 11 | ```typescript 12 | // 重载 13 | function sayHi(name: string): string; 14 | function sayHi(names: string[]): string[]; 15 | 16 | // 实现 17 | function sayHi(name: unknown): unknown { 18 | if (typeof name === 'string') { 19 | return `Hi, ${name}!`; 20 | } else if (Array.isArray(name)) { 21 | return name.map(name => `Hi, ${name}!`); 22 | } 23 | throw new Error('Invalid value'); 24 | } 25 | 26 | sayHi('xx'); // 有效 27 | sayHi(['aa', 'bb']); // 有效 28 | ``` 29 | 30 | 这是在 `class` 中使用函数重载的另一个示例: 31 | 32 | ```typescript 33 | class Greeter { 34 | message: string; 35 | 36 | constructor(message: string) { 37 | this.message = message; 38 | } 39 | 40 | // 重载 41 | sayHi(name: string): string; 42 | sayHi(names: string[]): ReadonlyArray; 43 | 44 | // 实现 45 | sayHi(name: unknown): unknown { 46 | if (typeof name === 'string') { 47 | return `${this.message}, ${name}!`; 48 | } else if (Array.isArray(name)) { 49 | return name.map(name => `${this.message}, ${name}!`); 50 | } 51 | throw new Error('value is invalid'); 52 | } 53 | } 54 | console.log(new Greeter('Hello').sayHi('Simon')); 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/predefined-conditional-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 预定义条件类型 3 | sidebar: 4 | order: 42 5 | label: 42. 预定义条件类型 6 | --- 7 | 8 | 9 | 在 TypeScript 中,预定义的条件类型是语言提供的内置条件类型。它们旨在根据给定类型的特征执行常见的类型转换。 10 | 11 | `Exclude`: 此类型从 Type 中删除可分配给 ExcludedType 的所有类型。 12 | 13 | `Extract`: 此类型从 Union 中提取可分配给 Type 的所有类型。 14 | 15 | `NonNullable`: 此类型从 Type 中删除 null 和 undefined。 16 | 17 | `ReturnType`: 此类型提取函数 Type 的返回类型。 18 | 19 | `Parameters`: 该类型提取函数类型的参数类型。 20 | 21 | `Required`: 此类型使 Type 中的所有属性成为必需。 22 | 23 | `Partial`: 此类型使 Type 中的所有属性都是可选的。 24 | 25 | `Readonly`: 此类型使 Type 中的所有属性变为只读。 26 | 27 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/readonly-properties.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 只读属性 3 | sidebar: 4 | order: 13 5 | label: 13. 只读属性 6 | --- 7 | 8 | 9 | 是否可以通过使用修饰符来防止对属性进行写入,`readonly` 以确保该属性不能被重写,但不提供任何完全不变性的保证: 10 | 11 | ```typescript 12 | interface Y { 13 | readonly a: number; 14 | } 15 | 16 | type X = { 17 | readonly a: number; 18 | }; 19 | 20 | type J = Readonly<{ 21 | a: number; 22 | }>; 23 | 24 | type K = { 25 | readonly [index: number]: string; 26 | }; 27 | ``` 28 | 29 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/strictnullchecks.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 严格空检查 3 | sidebar: 4 | order: 18 5 | label: 18. 严格空检查 6 | --- 7 | 8 | 9 | `strictNullChecks` 是一个 TypeScript 编译器选项,强制执行严格的 null 检查。启用此选项后,只有在变量和参数已使用联合类型 `null` | `undefined` 显式声明为该类型时,才可以对其进行赋值`null` 或者 `undefined`。如果变量或参数未显式声明为可为空,TypeScript 将生成错误以防止潜在的运行时错误。 10 | 11 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/symbols.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Symbols 3 | sidebar: 4 | order: 58 5 | label: 58. Symbols 6 | --- 7 | 8 | 9 | 符号是一种原始数据类型,表示不可变值,保证在程序的整个生命周期中全局唯一。 10 | 11 | 符号可以用作对象属性的键,并提供一种创建不可枚举属性的方法。 12 | 13 | ```typescript 14 | const key1: symbol = Symbol('key1'); 15 | const key2: symbol = Symbol('key2'); 16 | 17 | const obj = { 18 | [key1]: 'value 1', 19 | [key2]: 'value 2', 20 | }; 21 | 22 | console.log(obj[key1]); // value 1 23 | console.log(obj[key2]); // value 2 24 | ``` 25 | 26 | 在 WeakMap 和 WeakSet 中,现在允许符号作为键。 27 | 28 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/template-union-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 模板联合类型 3 | sidebar: 4 | order: 43 5 | label: 43. 模板联合类型 6 | --- 7 | 8 | 9 | 模板联合类型可用于合并和操作类型系统内的文本,例如: 10 | 11 | ```typescript 12 | type Status = 'active' | 'inactive'; 13 | type Products = 'p1' | 'p2'; 14 | type ProductId = `id-${Products}-${Status}`; // "id-p1-active" | "id-p1-inactive" | "id-p2-active" | "id-p2-inactive" 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/the-concise-typescript-book.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 简洁的TypeScript之书 3 | sidebar: 4 | order: 1 5 | label: 1. 简洁的TypeScript之书 6 | --- 7 | 8 | 9 | 《Concise TypeScript Book》全面而简洁地概述了 TypeScript 的功能。它提供了清晰的解释,涵盖了该语言最新版本中的所有方面,从强大的类型系统到高级功能。无论您是初学者还是经验丰富的开发人员,本书都是增强您对 TypeScript 的理解和熟练程度的宝贵资源。 10 | 11 | 本书完全免费且开源。 12 | 13 | 如果您发现这本 TypeScript 书籍很有价值并希望做出贡献,请考虑通过 PayPal 支持我的努力。谢谢! 14 | 15 | [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/donate/?business=QW82ZS956XLFY&no_recurring=0¤cy_code=EUR) 16 | 17 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/the-never-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: never 类型 3 | sidebar: 4 | order: 25 5 | label: 25. never 类型 6 | --- 7 | 8 | 9 | 当变量缩小为不能包含任何值的类型时,TypeScript 编译器将推断该变量必须属于该never类型。这是因为 never 类型代表永远无法生成的值。 10 | 11 | ```typescript 12 | const printValue = (val: string | number) => { 13 | if (typeof val === 'string') { 14 | console.log(val.toUpperCase()); 15 | } else if (typeof val === 'number') { 16 | console.log(val.toFixed(2)); 17 | } else { 18 | // val 在这里的类型为 never,因为它只能是字符串或数字 19 | const neverVal: never = val; 20 | console.log(`Unexpected value: ${neverVal}`); 21 | } 22 | }; 23 | ``` 24 | 25 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/translations.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 翻译 3 | sidebar: 4 | order: 2 5 | label: 2. 翻译 6 | --- 7 | 8 | 9 | 本书已被翻译成多种语言版本,包括: 10 | 11 | [中文](https://github.com/gibbok/typescript-book/blob/main/README-zh_CN.md) 12 | 13 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/triple-slash-directives.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 三斜杠指令 3 | sidebar: 4 | order: 59 5 | label: 59. 三斜杠指令 6 | --- 7 | 8 | 9 | 三斜杠指令是特殊注释,为编译器提供有关如何处理文件的说明。这些指令以三个连续斜杠 (`///`) 开头,通常放置在 TypeScript 文件的顶部,对运行时行为没有影响。 10 | 11 | 三斜杠指令用于引用外部依赖项、指定模块加载行为、启用/禁用某些编译器功能等等。几个例子: 12 | 13 | 引用声明文件: 14 | 15 | 16 | ```typescript 17 | /// 18 | ``` 19 | 20 | 指明模块格式: 21 | 22 | 23 | ```typescript 24 | /// 25 | ``` 26 | 27 | 启用编译器选项,在以下示例中严格模式: 28 | 29 | 30 | ```typescript 31 | /// 32 | ``` 33 | 34 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/tuple-type-anonymous.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 元组类型(匿名) 3 | sidebar: 4 | order: 28 5 | label: 28. 元组类型(匿名) 6 | --- 7 | 8 | 9 | 元组类型是一种表示具有固定数量的元素及其相应类型的数组的类型。元组类型以固定顺序强制执行特定数量的元素及其各自的类型。当您想要表示具有特定类型的值的集合时,元组类型非常有用,其中数组中每个元素的位置都有特定的含义。 10 | 11 | ```typescript 12 | type Point = [number, number]; 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/type-annotations.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 类型注释 3 | sidebar: 4 | order: 11 5 | label: 11. 类型注释 6 | --- 7 | 8 | 9 | 在使用 `var` 、 `let` 和 `const` 声明变量时,可以选择添加类型: 10 | 11 | ```typescript 12 | const x: number = 1; 13 | ``` 14 | 15 | TypeScript 在推断类型方面做得很好,尤其是简单类型时,因此在大多数情况下这些声明是不必要的。 16 | 17 | 在函数上可以向参数添加类型注释: 18 | 19 | ```typescript 20 | function sum(a: number, b: number) { 21 | return a + b; 22 | } 23 | ``` 24 | 25 | 以下是使用匿名函数(所谓的 lambda 函数)的示例: 26 | 27 | ```typescript 28 | const sum = (a: number, b: number) => a + b; 29 | ``` 30 | 31 | 当参数存在默认值时可以避免这些注释: 32 | 33 | ```typescript 34 | const sum = (a = 10, b: number) => a + b; 35 | ``` 36 | 37 | 可以将返回类型注释添加到函数中: 38 | 39 | ```typescript 40 | const sum = (a = 10, b: number): number => a + b; 41 | ``` 42 | 43 | 这对于更复杂的函数尤其有用,因为在实现之前编写显式返回类型可以帮助更好地思考该函数。 44 | 45 | 通常考虑注释类型签名,但不注释主体局部变量,并始终将类型添加到对象字面量中。 46 | 47 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/type-from-func-return.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Func 返回值的类型 3 | sidebar: 4 | order: 35 5 | label: 35. Func 返回值的类型 6 | --- 7 | 8 | 9 | Func Return 中的类型是指根据函数的实现自动推断函数的返回类型的能力。这允许 TypeScript 无需显式类型注释即可确定函数返回值的类型。 10 | 11 | ```typescript 12 | const add = (x: number, y: number) => x + y; // TypeScript 可以推断函数的返回类型是数字 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/type-from-module.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 模块的类型 3 | sidebar: 4 | order: 36 5 | label: 36. 模块的类型 6 | --- 7 | 8 | 9 | 模块的类型是指使用模块的导出值自动推断其类型的能力。当模块导出特定类型的值时,TypeScript 可以使用该信息在将该值导入到另一个模块时自动推断该值的类型。 10 | 11 | 12 | ```typescript 13 | export const add = (x: number, y: number) => x + y; 14 | // index.ts 15 | import { add } from 'calc'; 16 | const r = add(1, 2); // r 是 number 类型 17 | ``` 18 | 19 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/type-from-value.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 值的类型 3 | sidebar: 4 | order: 34 5 | label: 34. 值的类型 6 | --- 7 | 8 | 9 | TypeScript 中的"Type from Value"是指通过类型推断从值或表达式自动推断出类型。 10 | 11 | ```typescript 12 | const x = 'x'; // TypeScript 可以自动推断变量的类型是 string 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/type-indexing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 类型索引 3 | sidebar: 4 | order: 33 5 | label: 33. 类型索引 6 | --- 7 | 8 | 9 | 类型索引是指能够通过预先未知的键来定义可以索引的类型,使用索引签名来指定未显式声明的属性的类型。 10 | 11 | ```typescript 12 | type Dictionary = { 13 | [key: string]: T; 14 | }; 15 | const myDict: Dictionary = { a: 'a', b: 'b' }; 16 | console.log(myDict['a']); // 返回 a 17 | ``` 18 | 19 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/type-predicates.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 类型谓词 3 | sidebar: 4 | order: 23 5 | label: 23. 类型谓词 6 | --- 7 | 8 | 9 | TypeScript 中的类型谓词是返回布尔值的函数,用于将变量的类型缩小为更具体的类型。 10 | 11 | ```typescript 12 | const isString = (value: unknown): value is string => typeof value === 'string'; 13 | 14 | const foo = (bar: unknown) => { 15 | if (isString(bar)) { 16 | console.log(bar.toUpperCase()); 17 | } else { 18 | console.log('not a string'); 19 | } 20 | }; 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/union-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 联合类型 3 | sidebar: 4 | order: 31 5 | label: 31. 联合类型 6 | --- 7 | 8 | 9 | 联合类型是一种表示值的类型,该值可以是多种类型之一。联合类型使用 `|` 表示 每种可能类型之间的符号。 10 | 11 | ```typescript 12 | let x: string | number; 13 | x = 'hello'; // 有效 14 | x = 123; // 有效 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/unknown-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 未知类型 3 | sidebar: 4 | order: 45 5 | label: 45. 未知类型 6 | --- 7 | 8 | 9 | 在 TypeScript 中,未知类型表示未知类型的值。与允许任何类型值的 `any` 类型不同,`unknown` 需要在以特定方式使用它之前进行类型检查或断言,因此在未首先断言或缩小到更具体的类型的情况下,不允许对 `unknown` 进行任何操作 。 10 | 11 | `unknown` 类型只能分配给任何类型和未知类型本身,它是any 的类型安全替代方案。 12 | 13 | 14 | ```typescript 15 | let value: unknown; 16 | 17 | let value1: unknown = value; // 有效 18 | let value2: any = value; // 有效 19 | let value3: boolean = value; // 无效 20 | let value4: number = value; // 无效 21 | ``` 22 | 23 | ```typescript 24 | const add = (a: unknown, b: unknown): number | undefined => 25 | typeof a === 'number' && typeof b === 'number' ? a + b : undefined; 26 | console.log(add(1, 2)); // 3 27 | console.log(add('x', 2)); // undefined 28 | ``` 29 | 30 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/void-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 空类型 3 | sidebar: 4 | order: 46 5 | label: 46. 空类型 6 | --- 7 | 8 | 9 | `void` 类型用于指示函数不返回值。 10 | 11 | ```typescript 12 | const sayHello = (): void => { 13 | console.log('Hello!'); 14 | }; 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Typescript Book 3 | description: The Concise TypeScript Book 4 | template: splash 5 | hero: 6 | tagline: 《Concise TypeScript Book》全面而简洁地概述了 TypeScript 7 | 的功能。它提供了清晰的解释,涵盖了该语言最新版本中的所有方面,从强大的类型系统到高级功能。无论您是初学者还是经验丰富的开发人员,本书都是增强您对 8 | TypeScript 的理解和熟练程度的宝贵资源。

本书完全免费且开源。 9 | actions: 10 | - text: 现在读! 11 | link: /typescript-book/zh-cn/book/the-concise-typescript-book/ 12 | icon: right-arrow 13 | variant: primary 14 | - text: GitHub 15 | link: https://github.com/gibbok/typescript-book 16 | icon: github 17 | variant: secondary 18 | - text: X.com 19 | link: https://twitter.com/gibbok_coding 20 | icon: x.com 21 | variant: secondary 22 | --- 23 | -------------------------------------------------------------------------------- /website/src/content/i18n/zh-cn.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /website/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /website/src/styles/custom.css: -------------------------------------------------------------------------------- 1 | /* Dark mode colors. */ 2 | :root { 3 | --sl-color-accent-low: #36113e; 4 | --sl-color-accent: #a400c0; 5 | --sl-color-accent-high: #e3b6ed; 6 | --sl-color-white: #ffffff; 7 | --sl-color-gray-1: #f2e9fd; 8 | --sl-color-gray-2: #c7bdd5; 9 | --sl-color-gray-3: #9581ae; 10 | --sl-color-gray-4: #614e78; 11 | --sl-color-gray-5: #412e55; 12 | --sl-color-gray-6: #2f1c42; 13 | --sl-color-black: #1c1425; 14 | } 15 | /* Light mode colors. */ 16 | :root[data-theme='light'] { 17 | --sl-color-accent-low: #ebc9f3; 18 | --sl-color-accent: #a700c3; 19 | --sl-color-accent-high: #4e0e5b; 20 | --sl-color-white: #1c1425; 21 | --sl-color-gray-1: #2f1c42; 22 | --sl-color-gray-2: #412e55; 23 | --sl-color-gray-3: #614e78; 24 | --sl-color-gray-4: #9581ae; 25 | --sl-color-gray-5: #c7bdd5; 26 | --sl-color-gray-6: #f2e9fd; 27 | --sl-color-gray-7: #f8f4fe; 28 | --sl-color-black: #ffffff; 29 | } -------------------------------------------------------------------------------- /website/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/strict" 3 | } --------------------------------------------------------------------------------