├── tools ├── .nvmrc ├── .vscode │ ├── settings.json │ └── launch.json ├── config.ts ├── .prettierrc ├── i18n.ts ├── test-md │ ├── README-zh_CN.md │ └── README.md ├── Makefile ├── tsconfig.json ├── utils.ts ├── package.json ├── format.ts ├── .markdownlint.json ├── lint.ts ├── make-books.sh ├── README.md ├── compile.ts └── make-website-content.py ├── website ├── .nvmrc ├── src │ ├── content │ │ ├── i18n │ │ │ └── zh-cn.json │ │ ├── docs │ │ │ ├── zh-cn │ │ │ │ ├── book │ │ │ │ │ ├── translations.md │ │ │ │ │ ├── void-type.md │ │ │ │ │ ├── type-from-value.md │ │ │ │ │ ├── union-type.md │ │ │ │ │ ├── introduction.md │ │ │ │ │ ├── strictnullchecks.md │ │ │ │ │ ├── tuple-type-anonymous.md │ │ │ │ │ ├── type-from-func-return.md │ │ │ │ │ ├── named-tuple-type-labeled.md │ │ │ │ │ ├── type-indexing.md │ │ │ │ │ ├── fixed-length-tuple.md │ │ │ │ │ ├── template-union-types.md │ │ │ │ │ ├── downloads-and-website.md │ │ │ │ │ ├── intersection-types.md │ │ │ │ │ ├── type-from-module.md │ │ │ │ │ ├── distributive-conditional-types.md │ │ │ │ │ ├── optional-properties.md │ │ │ │ │ ├── infer-type-inference-in-conditional-types.md │ │ │ │ │ ├── readonly-properties.md │ │ │ │ │ ├── assignments.md │ │ │ │ │ ├── type-predicates.md │ │ │ │ │ ├── erased-structural-types.md │ │ │ │ │ ├── index-signatures.md │ │ │ │ │ ├── conditional-types.md │ │ │ │ │ ├── literal-types.md │ │ │ │ │ ├── namespacing.md │ │ │ │ │ ├── symbols.md │ │ │ │ │ ├── built-in-type-primitives.md │ │ │ │ │ ├── any-type.md │ │ │ │ │ ├── the-concise-typescript-book.md │ │ │ │ │ ├── mapped-type-modifiers.md │ │ │ │ │ ├── about-the-author.md │ │ │ │ │ ├── the-never-type.md │ │ │ │ │ ├── common-built-in-js-objects.md │ │ │ │ │ ├── predefined-conditional-types.md │ │ │ │ │ ├── mapped-types.md │ │ │ │ │ ├── triple-slash-directives.md │ │ │ │ │ ├── object-types.md │ │ │ │ │ ├── exhaustiveness-checking.md │ │ │ │ │ ├── unknown-type.md │ │ │ │ │ ├── merging-and-extension.md │ │ │ │ │ ├── type-annotations.md │ │ │ │ │ ├── extending-types.md │ │ │ │ │ ├── discriminated-unions.md │ │ │ │ │ ├── literal-inference.md │ │ │ │ │ ├── never-type.md │ │ │ │ │ ├── control-flow-analysis.md │ │ │ │ │ ├── overloads.md │ │ │ │ │ ├── differences-between-type-and-interface.md │ │ │ │ │ ├── interface-and-type.md │ │ │ │ │ ├── narrowing.md │ │ │ │ │ ├── generics.md │ │ │ │ │ ├── primitive-types.md │ │ │ │ │ ├── enums.md │ │ │ │ │ ├── table-of-contents.md │ │ │ │ │ ├── getting-started-with-typescript.md │ │ │ │ │ ├── typescript-introduction.md │ │ │ │ │ └── type-manipulation.md │ │ │ │ └── index.mdx │ │ │ ├── book │ │ │ │ ├── translations.md │ │ │ │ ├── void-type.md │ │ │ │ ├── union-type.md │ │ │ │ ├── type-from-value.md │ │ │ │ ├── downloads-and-website.md │ │ │ │ ├── template-union-types.md │ │ │ │ ├── named-tuple-type-labeled.md │ │ │ │ ├── type-indexing.md │ │ │ │ ├── type-from-func-return.md │ │ │ │ ├── intersection-types.md │ │ │ │ ├── introduction.md │ │ │ │ ├── strictnullchecks.md │ │ │ │ ├── optional-properties.md │ │ │ │ ├── type-predicates.md │ │ │ │ ├── tuple-type-anonymous.md │ │ │ │ ├── index-signatures.md │ │ │ │ ├── infer-type-inference-in-conditional-types.md │ │ │ │ ├── readonly-properties.md │ │ │ │ ├── type-from-module.md │ │ │ │ ├── distributive-conditional-types.md │ │ │ │ ├── assignments.md │ │ │ │ ├── fixed-length-tuple.md │ │ │ │ ├── namespacing.md │ │ │ │ ├── conditional-types.md │ │ │ │ ├── erased-structural-types.md │ │ │ │ ├── symbols.md │ │ │ │ ├── literal-types.md │ │ │ │ ├── common-built-in-js-objects.md │ │ │ │ ├── mapped-type-modifiers.md │ │ │ │ ├── the-never-type.md │ │ │ │ ├── about-the-author.md │ │ │ │ ├── the-concise-typescript-book.md │ │ │ │ ├── extending-types.md │ │ │ │ ├── exhaustiveness-checking.md │ │ │ │ ├── discriminated-unions.md │ │ │ │ ├── any-type.md │ │ │ │ ├── unknown-type.md │ │ │ │ ├── predefined-conditional-types.md │ │ │ │ ├── mapped-types.md │ │ │ │ ├── triple-slash-directives.md │ │ │ │ ├── object-types.md │ │ │ │ ├── built-in-type-primitives.md │ │ │ │ ├── merging-and-extension.md │ │ │ │ ├── never-type.md │ │ │ │ ├── type-annotations.md │ │ │ │ ├── literal-inference.md │ │ │ │ ├── overloads.md │ │ │ │ ├── control-flow-analysis.md │ │ │ │ ├── differences-between-type-and-interface.md │ │ │ │ ├── interface-and-type.md │ │ │ │ ├── narrowing.md │ │ │ │ ├── generics.md │ │ │ │ ├── primitive-types.md │ │ │ │ ├── enums.md │ │ │ │ ├── table-of-contents.md │ │ │ │ ├── type-manipulation.md │ │ │ │ ├── typescript-introduction.md │ │ │ │ └── getting-started-with-typescript.md │ │ │ └── index.mdx │ │ └── config.ts │ ├── env.d.ts │ ├── assets │ │ └── houston.webp │ └── styles │ │ └── custom.css ├── tsconfig.json ├── .vscode │ ├── extensions.json │ └── launch.json ├── .prettierrc ├── .gitignore ├── package.json ├── public │ └── favicon.svg ├── astro.config.mjs └── README.md ├── .gitignore ├── downloads ├── typescript-book.epub ├── typescript-book.pdf ├── typescript-book-zh_CN.pdf └── typescript-book-zh_CN.epub ├── .github └── workflows │ ├── compile.sh │ ├── lint.sh │ └── validate-content.yml └── LICENSE.MD /tools/.nvmrc: -------------------------------------------------------------------------------- 1 | v19.7.0 2 | -------------------------------------------------------------------------------- /website/.nvmrc: -------------------------------------------------------------------------------- 1 | v19.7.0 2 | -------------------------------------------------------------------------------- /website/src/content/i18n/zh-cn.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | temp 3 | !.vscode 4 | -------------------------------------------------------------------------------- /tools/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | } -------------------------------------------------------------------------------- /website/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/strict" 3 | } -------------------------------------------------------------------------------- /website/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /downloads/typescript-book.epub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gibbok/typescript-book/HEAD/downloads/typescript-book.epub -------------------------------------------------------------------------------- /downloads/typescript-book.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gibbok/typescript-book/HEAD/downloads/typescript-book.pdf -------------------------------------------------------------------------------- /website/src/assets/houston.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gibbok/typescript-book/HEAD/website/src/assets/houston.webp -------------------------------------------------------------------------------- /downloads/typescript-book-zh_CN.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gibbok/typescript-book/HEAD/downloads/typescript-book-zh_CN.pdf -------------------------------------------------------------------------------- /downloads/typescript-book-zh_CN.epub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gibbok/typescript-book/HEAD/downloads/typescript-book-zh_CN.epub -------------------------------------------------------------------------------- /.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 -------------------------------------------------------------------------------- /website/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["astro-build.astro-vscode"], 3 | "unwantedRecommendations": [] 4 | } 5 | -------------------------------------------------------------------------------- /tools/config.ts: -------------------------------------------------------------------------------- 1 | export const PRETTIER_CONFIG_FILE_PATH = './.prettierrc' 2 | 3 | export const CODE_BLOCK_TS_REGEX = /```typescript([\s\S]*?)```/g; -------------------------------------------------------------------------------- /.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 -------------------------------------------------------------------------------- /tools/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 4, 4 | "semi": true, 5 | "singleQuote": true, 6 | "printWidth": 80, 7 | "arrowParens": "avoid" 8 | } -------------------------------------------------------------------------------- /website/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 4, 4 | "semi": true, 5 | "singleQuote": true, 6 | "printWidth": 80, 7 | "arrowParens": "avoid" 8 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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] -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /tools/test-md/README-zh_CN.md: -------------------------------------------------------------------------------- 1 | # 简洁 TypeScript 书 2 | TypeScript 有效开发简明指南。 **免费和开源**。 3 | ## 创建文件和文件夹 4 | 可使用 按钮访问文件资源管理器。 5 | ## 切换到另一个文件 6 | 您的所有文件和文件夹都在文件资源管理器中显示为树。 您可以通过单击树中的文件从一个文件切换到另一个文件。 7 | ### 新标题 8 | 一些家长内容。 9 | #### 嵌套内容 1 10 | 更多内容在这里。 11 | ##### 嵌套内容 2 12 | 内容甚至更多。 -------------------------------------------------------------------------------- /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/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/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/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/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/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 | -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /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/.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/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/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/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-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/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/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/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/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/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/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/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/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/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/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/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 infers 'x' as a string literal with 'const' (immutable), but widens it to 'string' with 'let' (reassignable). 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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/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/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/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/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 | -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /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/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/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/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/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/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/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/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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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/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/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/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/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/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/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/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/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/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/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/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/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 | -------------------------------------------------------------------------------- /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/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/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/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/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/public/favicon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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/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/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/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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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!" -------------------------------------------------------------------------------- /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 | head: [ 14 | { 15 | tag: 'script', 16 | attrs: { 17 | defer: true, 18 | src: 'https://static.cloudflareinsights.com/beacon.min.js', 19 | 'data-cf-beacon': 20 | '{"token": "949aed66281e40378ac479993d699897"}', 21 | }, 22 | }, 23 | ], 24 | title: 'TypeScript Book', 25 | customCss: ['./src/styles/custom.css'], 26 | social: { 27 | github: 'https://github.com/gibbok/typescript-book', 28 | 'x.com': 'https://twitter.com/gibbok_coding', 29 | }, 30 | defaultLocale: 'root', 31 | locales: { 32 | root: { 33 | label: 'English', 34 | lang: 'en', 35 | }, 36 | 'zh-cn': { 37 | label: '简体中文', 38 | lang: 'zh-CN', 39 | }, 40 | }, 41 | sidebar: [ 42 | { 43 | label: 'TypeScript Book', 44 | autogenerate: { directory: 'book' }, 45 | }, 46 | ], 47 | }), 48 | ], 49 | }); 50 | -------------------------------------------------------------------------------- /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/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/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/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/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/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/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/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/zh-cn/book/primitive-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 原始类型 3 | sidebar: 4 | order: 10 5 | label: 10. 原始类型 6 | --- 7 | 8 | 9 | TypeScript 支持 7 种基本类型。原始数据类型是指不是对象并且没有任何与其关联的方法的类型。在 TypeScript 中,所有原始类型都是不可变的,这意味着它们的值一旦分配就无法更改。 10 | 11 | ### string 12 | 13 | 原始 `string` 类型存储文本数据,并且值始终是双引号或单引号的。 14 | 15 | ```typescript 16 | const x: string = 'x'; 17 | const y: string = 'y'; 18 | ``` 19 | 20 | 如果字符串被反引号 (`) 字符包围,则字符串可以跨越多行: 21 | 22 | ```typescript 23 | let sentence: string = `xxx, 24 | yyy`; 25 | ``` 26 | 27 | ### boolean 28 | 29 | TypeScript 中的数据 `boolean` 类型存储二进制值,或者true或false。 30 | 31 | ```typescript 32 | const isReady: boolean = true; 33 | ``` 34 | 35 | ### number 36 | 37 | TypeScript 中的数据类型 `number` 用 64 位浮点值表示。类型 `number` 可以表示整数和分数。TypeScript 还支持十六进制、二进制和八进制,例如: 38 | 39 | ```typescript 40 | const decimal: number = 10; 41 | const hexadecimal: number = 0xa00d; // 十六进制数以 0x 开始 42 | const binary: number = 0b1010; // 二进制数以 0b 开始 43 | const octal: number = 0o633; // 八进制数以 0o 开始 44 | ``` 45 | 46 | ### bigInt 47 | 48 | `bigInt` 表示无法用 `number` 表示的非常大的数值 (253 – 1)。 49 | 50 | `bigInt` 可以通过调用内置函数 `BigInt()` 或添加 `n` 到任何整数数字字面量的末尾来创建: 51 | 52 | ```typescript 53 | const x: bigint = BigInt(9007199254740991); 54 | const y: bigint = 9007199254740991n; 55 | ``` 56 | 57 | 笔记: 58 | 59 | * `bigInt` 值不能与 `number` 混合,也不能与内置的 `Math` 一起使用,它们必须强制为相同的类型。 60 | * 仅当目标配置为 ES2020 或更高版本时,“bigInt”值才可用。 61 | 62 | ### symbol 63 | 64 | JavaScript 有一个原始函数 Symbol(),它创建一个全局唯一的引用。 65 | 66 | ```typescript 67 | let sym = Symbol('x'); // symbol 类型 68 | ``` 69 | 70 | ### null and undefined 71 | 72 | `null`和 `undefined` 类型都表示没有值或不存在任何值。 73 | 74 | `undefined` 类型意味着该值未分配或初始化,或者指示无意中缺少值。 75 | 76 | `null` 类型意味着我们知道该字段没有值,因此值不可用,这表明故意不存在值。 77 | 78 | ### Array 79 | 80 | `array` 是一种可以存储多个相同类型或不同类型的值的数据类型。可以使用以下语法定义它: 81 | 82 | ```typescript 83 | const x: string[] = ['a', 'b']; 84 | const y: Array = ['a', 'b']; 85 | const j: Array = ['a', 1, 'b', 2]; 86 | ``` 87 | 88 | TypeScript 使用以下语法支持只读数组: 89 | 90 | 91 | ```typescript 92 | const x: readonly string[] = ['a', 'b']; // 只读修饰符 93 | const y: ReadonlyArray = ['a', 'b']; 94 | const j: ReadonlyArray = ['a', 1, 'b', 2]; 95 | j.push('x'); // 有效 96 | ``` 97 | 98 | TypeScript 支持数组和只读数组: 99 | 100 | ```typescript 101 | const x: [string, number] = ['a', 1]; 102 | const y: readonly [string, number] = ['a', 1]; 103 | ``` 104 | 105 | ### any 106 | 107 | 数据 `any` 类型字面上代表"任何"值,当 TypeScript 无法推断类型或未指定时,它是默认值。 108 | 109 | 使用 `any` 时,TypeScript编译器会跳过类型检查,因此 `any` 使用时不存在类型安全。通常,当发生错误时不要使用 `any` 静默编译器,而是专注于修复错误,因为使用 `any` 它可能会破坏契约,并且我们会失去 TypeScript 自动完成的好处。 110 | 111 | 在从 JavaScript 逐步迁移到 TypeScript 的过程中,该 `any` 类型可能很有用,因为它可以让编译器保持沉默。 112 | 113 | 对于新项目,请使用 TypeScript 配置 `noImplicitAny` ,该配置使 TypeScript 能够在any使用或推断时发出错误。 114 | 115 | `any` 通常是错误的来源,它可以掩盖类型的实际问题。尽可能避免使用它。 116 | 117 | -------------------------------------------------------------------------------- /website/src/content/docs/book/narrowing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Narrowing 3 | sidebar: 4 | order: 20 5 | label: 20. Narrowing 6 | --- 7 | 8 | 9 | TypeScript narrowing is the process of refining the type of a variable within a conditional block. This is useful when working with union types, where a variable can have more than one type. 10 | 11 | TypeScript recognizes several ways to narrow the type: 12 | 13 | ### typeof type guards 14 | 15 | The typeof type guard is one specific type guard in TypeScript that checks the type of a variable based on its built-in JavaScript type. 16 | 17 | ```typescript 18 | const fn = (x: number | string) => { 19 | if (typeof x === 'number') { 20 | return x + 1; // x is number 21 | } 22 | return -1; 23 | }; 24 | ``` 25 | 26 | ### Truthiness narrowing 27 | 28 | Truthiness narrowing in TypeScript works by checking whether a variable is truthy or falsy to narrow its type accordingly. 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 | ### Equality narrowing 41 | 42 | Equality narrowing in TypeScript works by checking whether a variable is equal to a specific value or not, to narrow its type accordingly. 43 | 44 | It is used in conjunction with `switch` statements and equality operators such as `===`, `!==`, `==`, and `!=` to narrow down types. 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 Operator narrowing 58 | 59 | The `in` Operator narrowing in TypeScript is a way to narrow the type of a variable based on whether a property exists within the variable's type. 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 narrowing 82 | 83 | The `instanceof` operator narrowing in TypeScript is a way to narrow the type of a variable based on its constructor function, by checking if an object is an instance of a certain class or interface. 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/enums.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 枚举 3 | sidebar: 4 | order: 19 5 | label: 19. 枚举 6 | --- 7 | 8 | 9 | 在 TypeScript 中,枚举是一组命名常量值。 10 | 11 | ```typescript 12 | enum Color { 13 | Red = '#ff0000', 14 | Green = '#00ff00', 15 | Blue = '#0000ff', 16 | } 17 | ``` 18 | 19 | 枚举可以用不同的方式定义: 20 | 21 | ### 数字枚举 22 | 23 | 在 TypeScript 中,数字枚举是一个枚举,其中每个常量都分配有一个数值,默认从 0 开始。 24 | 25 | ```typescript 26 | enum Size { 27 | Small, // 值从 0 开始 28 | Medium, 29 | Large, 30 | } 31 | ``` 32 | 33 | 可以通过显式分配来指定自定义值: 34 | 35 | ```typescript 36 | enum Size { 37 | Small = 10, 38 | Medium, 39 | Large, 40 | } 41 | console.log(Size.Medium); // 11 42 | ``` 43 | 44 | ### 字符串枚举 45 | 46 | 在 TypeScript 中,字符串枚举是每个常量都分配有一个字符串值的枚举。 47 | 48 | ```typescript 49 | enum Language { 50 | English = 'EN', 51 | Spanish = 'ES', 52 | } 53 | ``` 54 | 55 | 注意:TypeScript 允许使用异构枚举,其中字符串和数字成员可以共存。 56 | 57 | ### 常量枚举 58 | 59 | TypeScript 中的常量枚举是一种特殊类型的枚举,其中所有值在编译时都是已知的,并且在使用枚举的任何地方都会内联,从而产生更高效的代码。 60 | 61 | ```typescript 62 | const enum Language { 63 | English = 'EN', 64 | Spanish = 'ES', 65 | } 66 | console.log(Language.English); 67 | ``` 68 | 69 | 将被编译成: 70 | 71 | ```typescript 72 | console.log('EN' /* Language.English */); 73 | ``` 74 | 75 | 注意:常量枚举具有硬编码值,擦除枚举,这在独立库中可能更有效,但通常是不可取的。此外,常量枚举不能有计算成员。 76 | 77 | ### 反向映射 78 | 79 | 在 TypeScript 中,枚举中的反向映射是指从值中检索枚举成员名称的能力。默认情况下,枚举成员具有从名称到值的正向映射,但可以通过为每个成员显式设置值来创建反向映射。当您需要按枚举成员的值查找枚举成员,或者需要迭代所有枚举成员时,反向映射非常有用。需要注意的是,只有数字类型的枚举成员会生成反向映射,字符串类型的枚举成员则不会。 80 | 81 | 以下枚举: 82 | 83 | ```typescript 84 | enum Grade { 85 | A = 90, 86 | B = 80, 87 | C = 70, 88 | F = 'fail', 89 | } 90 | ``` 91 | 92 | 编译为: 93 | 94 | 95 | ```javascript 96 | 'use strict'; 97 | var Grade; 98 | (function (Grade) { 99 | Grade[(Grade['A'] = 90)] = 'A'; 100 | Grade[(Grade['B'] = 80)] = 'B'; 101 | Grade[(Grade['C'] = 70)] = 'C'; 102 | Grade['F'] = 'fail'; 103 | })(Grade || (Grade = {})); 104 | ``` 105 | 106 | 由此可见,对数字类型的枚举成员,可以从枚举值映射回枚举名称,但对字符串类型的枚举成员无法这样做。 107 | 108 | 109 | ```typescript 110 | enum Grade { 111 | A = 90, 112 | B = 80, 113 | C = 70, 114 | F = 'fail', 115 | } 116 | const myGrade = Grade.A; 117 | console.log(Grade[myGrade]); // A 118 | console.log(Grade[90]); // A 119 | 120 | const failGrade = Grade.F; 121 | console.log(failGrade); // fail 122 | console.log(Grade[failGrade]); // 因为索引表达式的类型不是 'number',所以元素是隐式的 'any' 类型。 123 | ``` 124 | 125 | ### 环境枚举 126 | 127 | TypeScript 中的环境枚举是一种在声明文件 (*.d.ts) 中定义的枚举类型,没有关联的实现。它允许您定义一组命名常量,这些常量可以在不同文件中以类型安全的方式使用,而无需在每个文件中导入实现细节。 128 | 129 | ### 计算成员和常量成员 130 | 131 | 在 TypeScript 中,计算成员是枚举的成员,其值在运行时计算,而常量成员是其值在编译时设置且在运行时无法更改的成员。常规枚举中允许使用计算成员,而常规枚举和常量枚举中都允许使用常量成员。 132 | 133 | ```typescript 134 | // 常量成员 135 | enum Color { 136 | Red = 1, 137 | Green = 5, 138 | Blue = Red + Green, 139 | } 140 | console.log(Color.Blue); // 6 编译时生成 141 | ``` 142 | 143 | ```typescript 144 | // 计算成员 145 | enum Color { 146 | Red = 1, 147 | Green = Math.pow(2, 2), 148 | Blue = Math.floor(Math.random() * 3) + 1, 149 | } 150 | console.log(Color.Blue); // 运行时生成的随机数 151 | ``` 152 | 153 | 枚举由包含其成员类型的联合表示。每个成员的值可以通过常量或非常量表达式确定,拥有常量值的成员被分配字面量类型。为了说明这一点,请考虑类型 E 及其子类型 E.A、E.B 和 E.C 的声明。在本例中,E 表​​示联合 E.A | E.B | E.C 。 154 | 155 | ```typescript 156 | const identity = (value: number) => value; 157 | 158 | enum E { 159 | A = 2 * 5, // 数字字面量 160 | B = 'bar', // 字符串字面量 161 | C = identity(42), // 不透明计算 162 | } 163 | 164 | console.log(E.C); //42 165 | ``` 166 | 167 | -------------------------------------------------------------------------------- /website/src/content/docs/book/generics.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Generics 3 | sidebar: 4 | order: 55 5 | label: 55. Generics 6 | --- 7 | 8 | 9 | Generics allow you to create reusable components and functions that can work with multiple types. With generics, you can parameterize types, functions, and interfaces, allowing them to operate on different types without explicitly specifying them beforehand. 10 | 11 | Generics allow you to make code more flexible and reusable. 12 | 13 | ### Generic Type 14 | 15 | To define a generic type, you use angle brackets (`<>`) to specify the type parameters, for instance: 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 | ### Generic Classes 29 | 30 | Generics can be applied also to classes, in this way they can work with multiple types by using type parameters. This is useful to create reusable class definitions that can operate on different data types while maintaining type safety. 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 | ### Generic Constraints 53 | 54 | Generic parameters can be constrained using the `extends` keyword followed by a type or interface that the type parameter must satisfy. 55 | 56 | In the following example T it is must containing a properly `length` in order to be valid: 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); // Invalid 68 | ``` 69 | 70 | An interesting feature of generic introduced in version 3.4 RC is Higher order function type inference which introduced propagated generic type arguments: 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 | This functionality allows more easily typed safe pointfree style programming which is common in functional programming. 86 | 87 | ### Generic contextual narrowing 88 | 89 | Contextual narrowing for generics is the mechanism in TypeScript that allows the compiler to narrow down the type of a generic parameter based on the context in which it is used, it is useful when working with generic types in conditional statements: 90 | 91 | ```typescript 92 | function process(value: T): void { 93 | if (typeof value === 'string') { 94 | // Value is narrowed down to type 'string' 95 | console.log(value.length); 96 | } else if (typeof value === 'number') { 97 | // Value is narrowed down to type 'number' 98 | console.log(value.toFixed(2)); 99 | } 100 | } 101 | 102 | process('hello'); // 5 103 | process(3.14159); // 3.14 104 | ``` 105 | 106 | -------------------------------------------------------------------------------- /tools/README.md: -------------------------------------------------------------------------------- 1 | # Tools for Working with Markdown Books 2 | 3 | If you're working with Markdown books, here are some essential tools and commands to help you streamline your workflow. 4 | 5 | ## Installation 6 | 7 | Before you begin, ensure you have Node.js installed. To set up the required dependencies, use the following commands: 8 | 9 | In folder `tools` and `website`: 10 | 11 | ```shell 12 | nvm use 13 | npm install 14 | ``` 15 | 16 | ```shell 17 | brew install pandoc 18 | brew install epubcheck 19 | brew install --cask calibre 20 | ``` 21 | 22 | ## Commands 23 | 24 | Use `make` to run the main commands: 25 | 26 | * `make format`: Format Markdown files for books. 27 | * `make check`: Run several checks to ensure the Markdown files are valid. 28 | * `make website`: Create different Markdown pages for the website. 29 | * `make website-preview`: Build and preview website locally. 30 | * `make website-deploy`: Build and deploy website to GitHub Pages. 31 | * `make books`: Create .epub books. 32 | 33 | ### Formatting 34 | 35 | Consistent code formatting is crucial. To format all TypeScript snippets, we use Prettier. Execute the following command for formatting: 36 | 37 | ```shell 38 | npm run format 39 | ``` 40 | 41 | ### Compilation 42 | 43 | To compile TypeScript snippets within the Markdown files, utilize the following command: 44 | 45 | ```shell 46 | npm run compile 47 | ``` 48 | 49 | ### Linting 50 | 51 | To ensure that your Markdown files adhere to proper formatting rules, use the linting command: 52 | 53 | ```shell 54 | npm run lint:md 55 | ``` 56 | 57 | ### Linting and Formatting 58 | 59 | For a comprehensive process that includes linting all Markdown files, applying Prettier formatting to all TypeScript snippets, and compiling them using TypeScript, use the following command: 60 | 61 | ```shell 62 | npm run check 63 | ``` 64 | 65 | The project uses the [Markdown All in One](https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one)Visual Studio Code extension to automatically update the table of contents. 66 | 67 | Use the following command to install it: 68 | 69 | ```shell 70 | code --install-extension yzhang.markdown-all-in-one 71 | ``` 72 | 73 | ### Skipping Compilation 74 | 75 | If you have specific snippets in the Markdown files that you don't want to compile, simply add `` just before the TypeScript demarcation for those snippets. 76 | 77 | ### Epub Generation 78 | 79 | To generate Epub files from your Markdown books, navigate to the `tools` folder and run the following command: 80 | 81 | ```shell 82 | make-books.sh 83 | ``` 84 | 85 | After generating the Epub files, thoroughly test them, and once you're satisfied with the results, commit the changes. 86 | 87 | These tools will assist you in efficiently working with Markdown books and ensure a smooth and organized process. Happy writing! 88 | 89 | ## Debug EPUB Issues 90 | 91 | To debug the EPUB files you create, follow these steps: 92 | 93 | First, download and install Sigil. You can use the following command to install Sigil: 94 | 95 | ```shell 96 | brew install --cask sigil 97 | ``` 98 | 99 | Next, run an EPUB check to validate your EPUB file. For example: 100 | 101 | ```shell 102 | epubcheck ../downloads/typescript-book.epub 103 | ``` 104 | 105 | Finally, open the EPUB file using Sigil for detailed inspection. 106 | 107 | ## How to Contribute to This E-Book 108 | 109 | To contribute to this e-book, follow these steps: 110 | 111 | * Update the main Markdown file with your changes. 112 | * Run `make check` to ensure the linter and other checks pass. 113 | * Preview the website locally with `make website-preview` to make sure it works as expected. 114 | * Generate the e-books by running `make books`. 115 | * Submit your PR and share your awesome contributions! 116 | -------------------------------------------------------------------------------- /tools/compile.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs-extra'; 2 | import * as path from 'path'; 3 | import * as ts from "typescript"; 4 | import { marked } from 'marked'; 5 | import { pipe } from 'fp-ts/function' 6 | import { makeFilePath } from './utils'; 7 | import { languages } from './i18n'; 8 | 9 | const TEMP_DIR = 'temp' 10 | const SKIP_COMMENT = '' 11 | 12 | type ReportsInfo = Readonly<{ 13 | reports: ts.Diagnostic[], 14 | emitSkipped: boolean 15 | }> 16 | 17 | type TempFilePaths = ReadonlyArray 18 | 19 | type CodeSnippets = ReadonlyArray 20 | 21 | const exitScript = (emitSkipped: boolean) => { 22 | const ERROR_CODE = 1 23 | const SUCCESS_CODE = 0 24 | const exitCode = emitSkipped ? ERROR_CODE : SUCCESS_CODE; 25 | console.log(`Process exiting with code '${exitCode}'.`); 26 | exitCode === ERROR_CODE && process.exit(exitCode); 27 | } 28 | 29 | const compileAndReport = (options: ts.CompilerOptions) => (fileNames: TempFilePaths): ReportsInfo => { 30 | const program = ts.createProgram(fileNames, options); 31 | const emitResult = program.emit(); 32 | 33 | const reports = ts 34 | .getPreEmitDiagnostics(program) 35 | .concat(emitResult.diagnostics); 36 | 37 | return { 38 | reports, 39 | emitSkipped: emitResult.emitSkipped 40 | } 41 | } 42 | 43 | const logReports = (data: ReportsInfo) => { 44 | data.reports.forEach(diagnostic => { 45 | if (diagnostic.file) { 46 | const { line, character } = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start!); 47 | const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); 48 | console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); 49 | } else { 50 | console.log(ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n")); 51 | } 52 | }); 53 | return data.emitSkipped 54 | } 55 | 56 | const isTypeScriptCode = (token: marked.Token): token is marked.Tokens.Code => token.type === 'code' && token.lang === 'typescript'; 57 | 58 | const isSkipComment = (token: marked.Token): token is marked.Tokens.HTML => token.type === 'html' && token.text === `${SKIP_COMMENT}\n`; 59 | 60 | const extractCodeSnippets = (markdown: string): CodeSnippets => 61 | pipe( 62 | new marked.Lexer(), 63 | lexer => lexer.lex(markdown), 64 | tokens => { 65 | let skipIndex = -1 66 | return tokens.reduce((tokens, token, index) => { 67 | if (index === skipIndex) { 68 | skipIndex = -1 69 | return [...tokens] 70 | } 71 | if (isSkipComment(token)) { 72 | skipIndex = index + 1 73 | return [...tokens] 74 | } 75 | return [...tokens, token] 76 | }, []) 77 | }, 78 | tokens => tokens.filter(isTypeScriptCode), 79 | codes => codes.map(x => x.text) 80 | ) 81 | 82 | const makeTempFiles = (snippets: CodeSnippets): TempFilePaths => 83 | snippets.reduce((acc, snippet, index) => { 84 | const tempFile = path.join(__dirname, `temp/temp_${index}.ts`); 85 | fs.writeFileSync(tempFile, snippet); 86 | 87 | return [ 88 | ...acc, 89 | tempFile 90 | ] 91 | }, []) 92 | 93 | const processMarkdownFile = (inputPath: string): void => 94 | pipe( 95 | () => fs.removeSync(TEMP_DIR), 96 | () => fs.ensureDirSync(TEMP_DIR), 97 | () => fs.readFileSync(inputPath, 'utf-8'), 98 | extractCodeSnippets, 99 | makeTempFiles, 100 | compileAndReport({ 101 | noEmitOnError: true, 102 | noImplicitAny: true, 103 | target: ts.ScriptTarget.ESNext, 104 | module: ts.ModuleKind.CommonJS, 105 | moduleDetection: ts.ModuleDetectionKind.Force, 106 | noUnusedLocals: false, 107 | strict: true 108 | }), 109 | logReports, 110 | exitScript, 111 | ) 112 | 113 | for (const item of languages) { 114 | console.log("Compiling: ", item) 115 | processMarkdownFile(makeFilePath(item)); 116 | } 117 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/table-of-contents.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 目录表 3 | sidebar: 4 | order: 4 5 | label: 4. 目录表 6 | --- 7 | 8 | 9 | 10 | - 简洁的TypeScript之书 11 | - 翻译 12 | - 下载和网站 13 | - 目录表 14 | - 介绍 15 | - 关于作者 16 | - TypeScript简介 17 | - 什么是TypeScript? 18 | - 为什么选择 TypeScript? 19 | - TypeScript 和 JavaScript 20 | - TypeScript 代码生成 21 | - 现在的现代 JavaScript(降级) 22 | - TypeScript 入门 23 | - 安装 24 | - 配置 25 | - TypeScript 的配置文件 26 | - target 27 | - lib 28 | - strict 29 | - module 30 | - moduleResolution 31 | - esModuleInterop 32 | - jsx 33 | - skipLibCheck 34 | - files 35 | - include 36 | - exclude 37 | - importHelpers 38 | - 迁移到 TypeScript 的建议 39 | - 探索类型系统 40 | - TypeScript 的语言服务 41 | - 结构类型 42 | - TypeScript 的基本比较规则 43 | - 类型作为集合 44 | - 赋值类型:类型声明和类型断言 45 | - 类型声明 46 | - 类型断言 47 | - 非空断言 48 | - 环境声明 49 | - 属性检测和多余属性检测 50 | - 弱类型 51 | - 严格的对象字面量检测 (Freshness) 52 | - 类型推断 53 | - 更高级的推断 54 | - 类型加宽 55 | - 常量 56 | - 类型参数的 const 修饰符 57 | - 常量断言 58 | - 显式类型注释 59 | - 类型缩小 60 | - 条件 61 | - 抛错或者返回 62 | - 可区分联合 63 | - 用户定义的类型保护 64 | - 原始类型 65 | - string 66 | - boolean 67 | - number 68 | - bigInt 69 | - symbol 70 | - null and undefined 71 | - Array 72 | - any 73 | - 类型注释 74 | - 可选属性 75 | - 只读属性 76 | - 索引签名 77 | - 扩展类型 78 | - 字面量类型 79 | - 字面量推断 80 | - 严格空检查 81 | - 枚举 82 | - 数字枚举 83 | - 字符串枚举 84 | - 常量枚举 85 | - 反向映射 86 | - 环境枚举 87 | - 计算成员和常量成员 88 | - 缩小范围 89 | - typeof 类型保护 90 | - 真实性缩小 91 | - 相等缩小 92 | - In运算符缩小 93 | - instanceof 缩小 94 | - 赋值 95 | - 控制流分析 96 | - 类型谓词 97 | - 可区分联合 98 | - never 类型 99 | - 详尽性检查 100 | - 对象类型 101 | - 元组类型(匿名) 102 | - 命名元组类型(已标记) 103 | - 固定长度元组 104 | - 联合类型 105 | - 交集类型 106 | - 类型索引 107 | - 值的类型 108 | - Func 返回值的类型 109 | - 模块的类型 110 | - 映射类型 111 | - 映射类型修饰符 112 | - 条件类型 113 | - 分配条件类型 114 | - infer 条件类型中的类型推断 115 | - 预定义条件类型 116 | - 模板联合类型 117 | - 任意类型 118 | - 未知类型 119 | - 空类型 120 | - Never类型 121 | - 接口及类型 122 | - 通用语法 123 | - 基本类型 124 | - 对象和接口 125 | - 并集和交集类型 126 | - 内置原始数据类型 127 | - 常见的内置JS对象 128 | - 重载 129 | - 合并与扩展 130 | - 类型和接口之间的差异 131 | - Class 132 | - 通用语法 133 | - 构造函数 134 | - 私有和受保护的构造函数 135 | - 访问修饰符 136 | - Get 与 Set 137 | - 类中的自动访问器 138 | - this 139 | - 参数属性 140 | - 抽象类 141 | - 使用泛型 142 | - 装饰器 143 | - 类装饰器 144 | - 属性装饰器 145 | - 方法装饰器 146 | - Getter 和 Setter 装饰器 147 | - 装饰器元数据 148 | - 继承 149 | - 静态成员 150 | - 属性初始化 151 | - 方法重载 152 | - 泛型 153 | - 泛型类型 154 | - 泛型类 155 | - 泛型约束 156 | - 泛型上下文缩小 157 | - 擦除的结构类型 158 | - 命名空间 159 | - Symbols 160 | - 三斜杠指令 161 | - 类型操作 162 | - 从类型创建类型 163 | - 索引访问类型 164 | - 工具类型 165 | - Awaited\ 166 | - Partial\ 167 | - Required\ 168 | - Readonly\ 169 | - Record\ 170 | - Pick\ 171 | - Omit\ 172 | - Exclude\ 173 | - Extract\ 174 | - NonNullable\ 175 | - Parameters\ 176 | - ConstructorParameters\ 177 | - ReturnType\ 178 | - InstanceType\ 179 | - ThisParameterType\ 180 | - OmitThisParameter\ 181 | - ThisType\ 182 | - Uppercase\ 183 | - Lowercase\ 184 | - Capitalize\ 185 | - Uncapitalize\ 186 | - NoInfer\ 187 | - 其他 188 | - 错误和异常处理 189 | - 混合类 190 | - 异步语言特性 191 | - 迭代器和生成器 192 | - TsDocs JSDoc 参考 193 | - @types 194 | - JSX 195 | - ES6 模块 196 | - ES7 求幂运算符 197 | - for-await-of 语句 198 | - New target 元属性 199 | - 动态导入表达式 200 | - "tsc –watch" 201 | - 默认声明 202 | - 可选链 203 | - 空合并运算符 204 | - 模板字符串类型 205 | - 函数重载 206 | - 递归类型 207 | - 递归条件类型 208 | - Node 中的 ECMAScript 模块支持 209 | - 断言函数 210 | - 可变参数元组类型 211 | - 装箱类型 212 | - TypeScript 中的协变和逆变 213 | - 类型参数的可选方差注释 214 | - 模板字符串模式索引签名 215 | - satisfies操作符 216 | - 仅类型导入和导出 217 | - 使用声明和显式资源管理 218 | - 使用声明等待 219 | - 导入属性 220 | 221 | 222 | -------------------------------------------------------------------------------- /website/src/content/docs/book/primitive-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Primitive Types 3 | sidebar: 4 | order: 10 5 | label: 10. Primitive Types 6 | --- 7 | 8 | 9 | TypeScript supports 7 primitive types. A primitive data type refers to a type that is not an object and does not have any methods associated with it. In TypeScript, all primitive types are immutable, meaning their values cannot be changed once they are assigned. 10 | 11 | ### string 12 | 13 | The `string` primitive type stores textual data, and the value is always double or single-quoted. 14 | 15 | ```typescript 16 | const x: string = 'x'; 17 | const y: string = 'y'; 18 | ``` 19 | 20 | Strings can span multiple lines if surrounded by the backtick (`) character: 21 | 22 | ```typescript 23 | let sentence: string = `xxx, 24 | yyy`; 25 | ``` 26 | 27 | ### boolean 28 | 29 | The `boolean` data type in TypeScript stores a binary value, either `true` or `false`. 30 | 31 | ```typescript 32 | const isReady: boolean = true; 33 | ``` 34 | 35 | ### number 36 | 37 | A `number` data type in TypeScript is represented with a 64-bit floating point value. A `number` type can represent integers and fractions. 38 | TypeScript also supports hexadecimal, binary, and octal, for instance: 39 | 40 | ```typescript 41 | const decimal: number = 10; 42 | const hexadecimal: number = 0xa00d; // Hexadecimal starts with 0x 43 | const binary: number = 0b1010; // Binary starts with 0b 44 | const octal: number = 0o633; // Octal starts with 0o 45 | ``` 46 | 47 | ### bigInt 48 | 49 | A `bigInt` represents numeric values that are very large (253 – 1) and cannot be represented with a `number`. 50 | 51 | A `bigInt` can be created by calling the built-in function `BigInt()` or by adding `n` to the end of any integer numeric literal: 52 | 53 | ```typescript 54 | const x: bigint = BigInt(9007199254740991); 55 | const y: bigint = 9007199254740991n; 56 | ``` 57 | 58 | Notes: 59 | 60 | * `bigInt` values cannot be mixed with `number` and cannot be used with built-in `Math`, they must be coerced to the same type. 61 | * `bigInt` values are available only if target configuration is ES2020 or higher. 62 | 63 | ### Symbol 64 | 65 | Symbols are unique identifiers that can be used as property keys in objects to prevent naming conflicts. 66 | 67 | ```typescript 68 | type Obj = { 69 | [sym: symbol]: number; 70 | }; 71 | 72 | const a = Symbol('a'); 73 | const b = Symbol('b'); 74 | let obj: Obj = {}; 75 | obj[a] = 123; 76 | obj[b] = 456; 77 | 78 | console.log(obj[a]); // 123 79 | console.log(obj[b]); // 456 80 | ``` 81 | 82 | ### null and undefined 83 | 84 | `null` and `undefined` types both represent no value or the absence of any value. 85 | 86 | The `undefined` type means the value is not assigned or initialized or indicates an unintentional absence of value. 87 | 88 | The `null` type means that we know that the field does not have a value, so value is unavailable, it indicates an intentional absence of value. 89 | 90 | ### Array 91 | 92 | An `array` is a data type that can store multiple values of the same type or not. It can be defined using the following syntax: 93 | 94 | ```typescript 95 | const x: string[] = ['a', 'b']; 96 | const y: Array = ['a', 'b']; 97 | const j: Array = ['a', 1, 'b', 2]; // Union 98 | ``` 99 | 100 | TypeScript supports readonly arrays using the following syntax: 101 | 102 | 103 | ```typescript 104 | const x: readonly string[] = ['a', 'b']; // Readonly modifier 105 | const y: ReadonlyArray = ['a', 'b']; 106 | const j: ReadonlyArray = ['a', 1, 'b', 2]; 107 | j.push('x'); // Invalid 108 | ``` 109 | 110 | TypeScript supports tuple and readonly tuple: 111 | 112 | ```typescript 113 | const x: [string, number] = ['a', 1]; 114 | const y: readonly [string, number] = ['a', 1]; 115 | ``` 116 | 117 | ### any 118 | 119 | The `any` data type represents literally "any" value, it is the default value when TypeScript cannot infer the type or is not specified. 120 | 121 | When using `any` TypeScript compiler skips the type checking so there is no type safety when `any` is being used. Generally do not use `any` to silence the compiler when an error occurs, instead focus on fixing the error as with using `any` it is possible to break contracts and we lose the benefits of TypeScript autocomplete. 122 | 123 | The `any` type could be useful during a gradual migration from JavaScript to TypeScript, as it can silence the compiler. 124 | 125 | For new projects use TypeScript configuration `noImplicitAny` which enables TypeScript to issue errors where `any` is used or inferred. 126 | 127 | The `any`type is usually a source of errors which can mask real problems with your types. Avoid using it as much as possible. 128 | 129 | -------------------------------------------------------------------------------- /tools/make-website-content.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generate multiple Markdown documents from a single Markdown file by splitting it based on headings. 3 | This script is designed for creating pages on a website and provides results for multiple languages. 4 | Note: the number of headings per language must be the same. 5 | """ 6 | 7 | import os 8 | import re 9 | import shutil 10 | from typing import List 11 | 12 | 13 | # INPUT_FILE_PATH = "./test-md/README.md" 14 | # OUTPUT_DIR_PATH = "./test-md/en" 15 | # INPUT_FILE_PATH_CN = "./test-md/README-zh_CN.md" 16 | # OUTPUT_DIR_PATH_CN = "./test-md/zh-cn" 17 | 18 | INPUT_FILE_PATH = "../README.md" 19 | OUTPUT_DIR_PATH = "../website/src/content/docs/book" 20 | 21 | INPUT_FILE_PATH_CN = "../README-zh_CN.md" 22 | OUTPUT_DIR_PATH_CN = "../website/src/content/docs/zh-cn/book" 23 | 24 | 25 | def manage_output_dir(path: str) -> None: 26 | if os.path.exists(path): 27 | shutil.rmtree(path) 28 | os.makedirs(path) 29 | 30 | 31 | def read_content_file(path: str) -> List[str]: 32 | with open(path, "r") as file: 33 | lines = file.readlines() 34 | return lines 35 | 36 | 37 | def make_file_name(name: str) -> str: 38 | content_sanitized = re.sub(r"[^a-zA-Z0-9]+", "-", name.lower()).strip("-") 39 | return f"{content_sanitized}" 40 | 41 | 42 | def make_output_path(output_dir: str, file_name: str): 43 | return f"{output_dir}/{file_name}.md" 44 | 45 | 46 | def is_line_header_1_to_2(line: str) -> bool: 47 | return re.match(r"^(#{1,2})\s+(.+)", line) 48 | 49 | 50 | def make_file_output_path(output_dir: str, name: str) -> str: 51 | file_name = make_file_name(name) 52 | output_file_path = make_output_path(output_dir, file_name) 53 | return output_file_path 54 | 55 | 56 | def make_markdown_page_metadata(order: int, header: str) -> List[str]: 57 | return [ 58 | "---\n", 59 | f"title: {header}\n", 60 | "sidebar:\n", 61 | f" order: {order}\n", 62 | f" label: {order}. {header}\n", 63 | "---\n", 64 | "\n", 65 | ] 66 | 67 | 68 | def save_content_to_file(path: str, lines: List[str]): 69 | with open(path, "w") as output_file: 70 | output_file.writelines(lines) 71 | 72 | 73 | def save_pages_to_files( 74 | data_pages: List[List[str]], master_headers: List[str], output_dir: str 75 | ) -> None: 76 | for index, header in enumerate(master_headers): 77 | file = make_file_output_path(output_dir, header) 78 | save_content_to_file(file, data_pages[index]) 79 | 80 | 81 | def find_master_headers(lines: List[str]) -> List[str]: 82 | headers = [x for x in lines if is_line_header_1_to_2(x)] 83 | headers_clean = list(map(lambda x: make_file_name(x), headers)) 84 | return headers_clean 85 | 86 | 87 | def remove_markdown_anchors(markdown_text: str): 88 | pattern = r"\[(.*?)\]\(#[^\)]*\)" 89 | replacement = r"\1" 90 | transformed_text = re.sub(pattern, replacement, markdown_text) 91 | return transformed_text 92 | 93 | 94 | def split_content_by_headings(lines: List[str]): 95 | current_content = [] 96 | in_page = False 97 | header_index = -1 98 | content_result = [] 99 | 100 | for line in lines: 101 | is_header_match = is_line_header_1_to_2(line) 102 | if is_header_match: 103 | header_text = is_header_match.group(2).strip() 104 | header_index += 1 105 | if not in_page: 106 | in_page = True 107 | current_content.extend( 108 | make_markdown_page_metadata(header_index + 1, header_text) 109 | ) 110 | else: 111 | content_result.extend([current_content]) 112 | current_content = [] 113 | in_page = True 114 | current_content.extend( 115 | make_markdown_page_metadata(header_index + 1, header_text) 116 | ) 117 | else: 118 | line_new = remove_markdown_anchors(line) 119 | current_content.append(line_new) 120 | 121 | header_index += 1 122 | content_result.extend([current_content]) 123 | 124 | return content_result 125 | 126 | 127 | def process(base_input_path, input_lang_path: str, base_output_path: str) -> None: 128 | manage_output_dir(base_output_path) 129 | 130 | content_lines_master = read_content_file(base_input_path) 131 | master_headers = find_master_headers(content_lines_master) 132 | 133 | content_lines = read_content_file(input_lang_path) 134 | data_pages = split_content_by_headings( 135 | content_lines, 136 | ) 137 | save_pages_to_files(data_pages, master_headers, base_output_path) 138 | print(f"A total of: {len(master_headers)} files were at: {base_output_path}") 139 | 140 | 141 | process(INPUT_FILE_PATH, INPUT_FILE_PATH, OUTPUT_DIR_PATH) 142 | 143 | process(INPUT_FILE_PATH, INPUT_FILE_PATH_CN, OUTPUT_DIR_PATH_CN) 144 | -------------------------------------------------------------------------------- /website/src/content/docs/book/enums.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Enums 3 | sidebar: 4 | order: 19 5 | label: 19. Enums 6 | --- 7 | 8 | 9 | In TypeScript, an `enum` is a set of named constant values. 10 | 11 | ```typescript 12 | enum Color { 13 | Red = '#ff0000', 14 | Green = '#00ff00', 15 | Blue = '#0000ff', 16 | } 17 | ``` 18 | 19 | Enums can be defined in different ways: 20 | 21 | ### Numeric enums 22 | 23 | In TypeScript, a Numeric Enum is an Enum where each constant is assigned a numeric value, starting from 0 by default. 24 | 25 | ```typescript 26 | enum Size { 27 | Small, // value starts from 0 28 | Medium, 29 | Large, 30 | } 31 | ``` 32 | 33 | It is possible to specify custom values by explicitly assigning them: 34 | 35 | ```typescript 36 | enum Size { 37 | Small = 10, 38 | Medium, 39 | Large, 40 | } 41 | console.log(Size.Medium); // 11 42 | ``` 43 | 44 | ### String enums 45 | 46 | In TypeScript, a String enum is an Enum where each constant is assigned a string value. 47 | 48 | ```typescript 49 | enum Language { 50 | English = 'EN', 51 | Spanish = 'ES', 52 | } 53 | ``` 54 | 55 | Note: TypeScript allows the usage of heterogeneous Enums where string and numeric members can coexist. 56 | 57 | ### Constant enums 58 | 59 | A constant enum in TypeScript is a special type of Enum where all the values are known at compile time and are inlined wherever the enum is used, resulting in more efficient code. 60 | 61 | ```typescript 62 | const enum Language { 63 | English = 'EN', 64 | Spanish = 'ES', 65 | } 66 | console.log(Language.English); 67 | ``` 68 | 69 | Will be compiled into: 70 | 71 | ```typescript 72 | console.log('EN' /* Language.English */); 73 | ``` 74 | 75 | Notes: 76 | Const Enums have hardcoded values, erasing the Enum, which can be more efficient in self-contained libraries but is generally not desirable. Also, Const enums cannot have computed members. 77 | 78 | ### Reverse mapping 79 | 80 | In TypeScript, reverse mappings in Enums refer to the ability to retrieve the Enum member name from its value. By default, Enum members have forward mappings from name to value, but reverse mappings can be created by explicitly setting values for each member. Reverse mappings are useful when you need to look up an Enum member by its value, or when you need to iterate over all the Enum members. Note that only numeric enums members will generate reverse mappings, while String Enum members do not get a reverse mapping generated at all. 81 | 82 | The following enum: 83 | 84 | ```typescript 85 | enum Grade { 86 | A = 90, 87 | B = 80, 88 | C = 70, 89 | F = 'fail', 90 | } 91 | ``` 92 | 93 | Compiles to: 94 | 95 | 96 | ```javascript 97 | 'use strict'; 98 | var Grade; 99 | (function (Grade) { 100 | Grade[(Grade['A'] = 90)] = 'A'; 101 | Grade[(Grade['B'] = 80)] = 'B'; 102 | Grade[(Grade['C'] = 70)] = 'C'; 103 | Grade['F'] = 'fail'; 104 | })(Grade || (Grade = {})); 105 | ``` 106 | 107 | Therefore, mapping values to keys works for numeric enum members, but not for string enum members: 108 | 109 | 110 | ```typescript 111 | enum Grade { 112 | A = 90, 113 | B = 80, 114 | C = 70, 115 | F = 'fail', 116 | } 117 | const myGrade = Grade.A; 118 | console.log(Grade[myGrade]); // A 119 | console.log(Grade[90]); // A 120 | 121 | const failGrade = Grade.F; 122 | console.log(failGrade); // fail 123 | console.log(Grade[failGrade]); // Element implicitly has an 'any' type because index expression is not of type 'number'. 124 | ``` 125 | 126 | ### Ambient enums 127 | 128 | An ambient enum in TypeScript is a type of Enum that is defined in a declaration file (*.d.ts) without an associated implementation. It allows you to define a set of named constants that can be used in a type-safe way across different files without having to import the implementation details in each file. 129 | 130 | ### Computed and constant members 131 | 132 | In TypeScript, a computed member is a member of an Enum that has a value calculated at runtime, while a constant member is a member whose value is set at compile-time and cannot be changed during runtime. Computed members are allowed in regular Enums, while constant members are allowed in both regular and const enums. 133 | 134 | ```typescript 135 | // Constant members 136 | enum Color { 137 | Red = 1, 138 | Green = 5, 139 | Blue = Red + Green, 140 | } 141 | console.log(Color.Blue); // 6 generation at compilation time 142 | ``` 143 | 144 | ```typescript 145 | // Computed members 146 | enum Color { 147 | Red = 1, 148 | Green = Math.pow(2, 2), 149 | Blue = Math.floor(Math.random() * 3) + 1, 150 | } 151 | console.log(Color.Blue); // random number generated at run time 152 | ``` 153 | 154 | Enums are denoted by unions comprising their member types. The values of each member can be determined through constant or non-constant expressions, with members possessing constant values being assigned literal types. To illustrate, consider the declaration of type E and its subtypes E.A, E.B, and E.C. In this case, E represents the union E.A | E.B | E.C. 155 | 156 | ```typescript 157 | const identity = (value: number) => value; 158 | 159 | enum E { 160 | A = 2 * 5, // Numeric literal 161 | B = 'bar', // String literal 162 | C = identity(42), // Opaque computed 163 | } 164 | 165 | console.log(E.C); //42 166 | ``` 167 | 168 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/getting-started-with-typescript.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: TypeScript 入门 3 | sidebar: 4 | order: 8 5 | label: 8. TypeScript 入门 6 | --- 7 | 8 | 9 | ### 安装 10 | 11 | Visual Studio Code 为 TypeScript 语言提供了出色的支持,但不包含 TypeScript 编译器。要安装 TypeScript 编译器,您可以使用包管理器,例如 npm 或yarn: 12 | 13 | ```shell 14 | npm install typescript --save-dev 15 | ``` 16 | 17 | 或者 18 | 19 | ```shell 20 | yarn add typescript --dev 21 | ``` 22 | 23 | 确保提交生成的锁定文件,以确保每个团队成员使用相同版本的 TypeScript。 24 | 25 | 要运行TypeScript编译器,可以使用以下命令 26 | 27 | ```shell 28 | npx tsc 29 | ``` 30 | 31 | 或者 32 | 33 | ```shell 34 | yarn tsc 35 | ``` 36 | 37 | 建议按项目安装 TypeScript,而不是全局安装,因为它提供了更可预测的构建过程。但是,对于一次性情况,您可以使用以下命令: 38 | 39 | ```shell 40 | npx tsc 41 | ``` 42 | 43 | 或者安装到全局: 44 | 45 | ```shell 46 | npm install -g typescript 47 | ``` 48 | 49 | 如果您使用的是 Microsoft Visual Studio,则可以在 NuGet 中为 MSBuild 项目获取作为包的 TypeScript。在 NuGet 包管理器控制台中,运行以下命令: 50 | 51 | ```shell 52 | Install-Package Microsoft.TypeScript.MSBuild 53 | ``` 54 | 55 | 在 TypeScript 安装过程中,会安装两个可执行文件:"tsc"作为 TypeScript 编译器,"tsserver"作为 TypeScript 独立服务器。独立服务器包含编译器和语言服务,编辑器和 IDE 可以利用它们来提供智能代码补全。 56 | 57 | 此外,还有几种兼容 TypeScript 的转译器可用,例如 Babel(通过插件)或 swc。这些转译器可用于将 TypeScript 代码转换为其他目标语言或版本。 58 | 59 | ### 配置 60 | 61 | 可以使用 tsc CLI 选项或利用位于项目根目录中名为 tsconfig.json 的专用配置文件来配置 TypeScript。 62 | 63 | 要生成预填充推荐设置的 tsconfig.json 文件,您可以使用以下命令: 64 | 65 | ```shell 66 | tsc --init 67 | ``` 68 | 69 | 在本地执行tsc命令时,TypeScript 将使用最近的 tsconfig.json 文件中指定的配置来编译代码。 70 | 71 | 以下是使用默认设置运行的 CLI 命令的一些示例: 72 | 73 | ```shell 74 | tsc main.ts // 将一个特定的文件 (main.ts) 编译成 JavaScript 75 | tsc src/*.ts // 将 'src' 文件夹下任意的 .ts 文件编译成 JavaScript 76 | tsc app.ts util.ts --outfile index.js // 将 2 个 TypeScript 文件 (app.ts 和 util.ts) 编译成 1 个 JavaScript 文件 (index.js) 77 | ``` 78 | 79 | ### TypeScript 的配置文件 80 | 81 | tsconfig.json 文件用于配置 TypeScript 编译器 (tsc)。通常,它与文件一起添加到项目的根目录中package.json。 82 | 83 | 注意: 84 | 85 | * tsconfig.json 即使是 json 格式也接受注释。 86 | * 建议使用此配置文件而不是命令行选项。 87 | 88 | 在以下链接中,您可以找到完整的文档及其配置示例: 89 | 90 | [https://www.typescriptlang.org/tsconfig](https://www.typescriptlang.org/tsconfig) 91 | 92 | [http://json.schemastore.org/tsconfig](http://json.schemastore.org/tsconfig) 93 | 94 | 以下列出了常见且有用的配置: 95 | 96 | #### target 97 | 98 | "target"属性用于指定 TypeScript 应发出/编译到哪个版本的 JavaScript ECMAScript 版本。对于现代浏览器,ES6是一个不错的选择,对于较旧的浏览器,建议使用ES5。 99 | 100 | #### lib 101 | 102 | "lib"属性用于指定编译时要包含哪些库文件。TypeScript 自动包含"目标"属性中指定功能的 API,但可以根据特定需求省略或选择特定库。例如,如果您正在开发服务器项目,则可以排除"DOM"库,该库仅在浏览器环境中有用。 103 | 104 | #### strict 105 | 106 | "strict"属性可以提供更强有力的保证并增强类型安全性。建议始终将此属性包含在项目的 tsconfig.json 文件中。启用"strict"属性允许 TypeScript : 107 | 108 | * 触发每个源文件的代码使用"use strict"。 109 | * 在类型检查过程中考虑"null"和"undefined" 110 | * 当不存在类型注释时禁用"any"类型的使用。 111 | * 在使用"this"表达式时引发错误,否则"this"会被视为任意类型。 112 | 113 | #### module 114 | 115 | "module"属性设置编译程序支持的模块系统。在运行时,模块加载器用于根据指定的模块系统定位并执行依赖项。 116 | JavaScript 中最常见的模块加载器是用于服务器端应用程序的 Node.js 的CommonJS和用于基于浏览器的 Web 应用程序中的 AMD 模块的 RequireJS。 117 | TypeScript 可以为各种模块系统生成代码,包括 UMD、System、ESNext、ES2015/ES6 和 ES2020。 118 | 119 | 注意:应根据目标环境和该环境中可用的模块加载机制来选择模块系统。 120 | 121 | #### moduleResolution 122 | 123 | "moduleResolution"属性指定模块解析策略。对现代TypeScript代码使用"node","classic"仅用于旧版本的 TypeScript(1.6 之前)。 124 | 125 | #### esModuleInterop 126 | 127 | "esModuleInterop"属性允许从未使用"default"属性导出的 CommonJS 模块导入默认值,此属性提供了一个兼容以确保生成的 JavaScript 的兼容性。启用此选项后,我们可以使用 `import MyLibrary from "my-library"` 而不是 `import * as MyLibrary from "my-library"`。 128 | 129 | #### jsx 130 | 131 | "jsx"属性仅适用于 ReactJS 中使用的 .tsx 文件,并控制 JSX 构造如何编译为 JavaScript。一个常见的选项是"preserve",它将编译为 .jsx 文件,保持 JSX 不变,以便可以将其传递给 Babel 等不同工具进行进一步转换。 132 | 133 | #### skipLibCheck 134 | 135 | "skipLibCheck"属性将阻止 TypeScript 对整个导入的第三方包进行类型检查。此属性将减少项目的编译时间。TypeScript 仍会根据这些包提供的类型定义检查您的代码。 136 | 137 | #### files 138 | 139 | "files"属性向编译器指示必须始终包含在程序中的文件列表。 140 | 141 | #### include 142 | 143 | 144 | "include"属性向编译器指示我们想要包含的文件列表。此属性允许类似 glob 的模式,例如 "\*_" 表示任何子目录,"_" 表示任何文件名,"?" 表示可选字符。 145 | 146 | 147 | #### exclude 148 | 149 | "exclude"属性向编译器指示不应包含在编译中的文件列表。这可以包括"node_modules"等文件或测试文件 150 | 注意:tsconfig.json 允许注释。 151 | 152 | ### importHelpers 153 | 154 | TypeScript 在为某些高级或低级 JavaScript 功能生成代码时使用帮助程序代码。 默认情况下,这些助手会在使用它们的文件中复制。 `importHelpers` 选项从 `tslib` 模块导入这些帮助器,从而使 JavaScript 输出更加高效。 155 | 156 | ### 迁移到 TypeScript 的建议 157 | 158 | 对于大型项目,建议采用逐渐过渡的方式,其中 TypeScript 和 JavaScript 代码最初共存。只有小型项目才能一次性迁移到 TypeScript。 159 | 160 | 此转变的第一步是将 TypeScript 引入构建链过程。这可以通过使用"allowJs"编译器选项来完成,该选项允许 .ts 和 .tsx 文件与现有 JavaScript 文件共存。由于当 TypeScript 无法从 JavaScript 文件推断类型时,它会回退到变量的"any"类型,因此建议在迁移开始时在编译器选项中禁用"noImplicitAny"。 161 | 162 | 第二步是确保您的 JavaScript 测试与 TypeScript 文件一起工作,以便您可以在转换每个模块时运行测试。如果您正在使用 Jest,请考虑使用ts-jest,它允许您使用 Jest 测试 TypeScript 项目。 163 | 164 | 第三步是在项目中包含第三方库的类型声明。 这些声明可以第三方库的类型声明文件或专门的声明包中找到,你能通过 [https://www.typescriptlang.org/dt/search](https://www.typescriptlang.org/dt/search) 搜索并安装它们。: 165 | 166 | ```shell 167 | npm install --save-dev @types/package-name or yarn add --dev @types/package-name. 168 | ``` 169 | 170 | 第四步是使用自下而上的方法逐个模块地迁移,遵循从叶开始的依赖关系图。这个想法是开始转换不依赖于其他模块的模块。要可视化依赖关系图,您可以使用该madge工具。 171 | 172 | 有一些对于转换成 TypeScript 比较友好的模块(外部 API 或规范相关的实用函数和代码),比如Swagger、GraphQL 或 JSONSchema 自动生成 TypeScript 类型定义,并使用在您的项目中。 173 | 174 | 当没有可用的规范或官方架构时,您可以从原始数据生成类型,例如服务器返回的 JSON。但是,建议从规范而不是数据生成类型,以避免丢失边缘情况。 175 | 176 | 在迁移过程中,不要进行代码重构,而只专注于向模块添加类型。 177 | 178 | 第五步是启用"noImplicitAny",这将强制所有类型都是已知和定义的,从而为您的项目提供更好的 TypeScript 体验。 179 | 180 | 在迁移过程中,您可以使用该@ts-check指令,该指令在 JavaScript 文件中启用 TypeScript 类型检查。该指令提供了宽松版本的类型检查,最初可用于识别 JavaScript 文件中的问题。当@ts-check包含在文件中时,TypeScript 将尝试使用 JSDoc 风格的注释来推断定义。但是,仅在迁移的早期阶段考虑使用 JSDoc 注释。 181 | 182 | 考虑在你的tsconfig.json文件中将 `noEmitOnError` 设置为 false,即使报告错误,这也将允许您输出 JavaScript 源代码。 183 | 184 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/typescript-introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: TypeScript简介 3 | sidebar: 4 | order: 7 5 | label: 7. TypeScript简介 6 | --- 7 | 8 | 9 | ### 什么是TypeScript? 10 | 11 | TypeScript 是一种基于 JavaScript 构建的强类型编程语言。它最初由 Anders Hejlsberg 于 2012 年设计,目前由 Microsoft 作为开源项目开发和维护。 12 | 13 | TypeScript 编译为 JavaScript,并且可以在任何 JavaScript 运行时(例如浏览器或服务器 Node.js)中执行。 14 | 15 | TypeScript 支持多种编程范式,例如函数式、泛型、命令式和面向对象。TypeScript 既不是解释型语言,也不是编译型语言。 16 | 17 | ### 为什么选择 TypeScript? 18 | 19 | TypeScript 是一种强类型语言,有助于防止常见的编程错误,并在程序执行之前避免某些类型的运行时错误。 20 | 21 | 强类型语言允许开发人员在数据类型定义中指定各种程序约束和行为,从而有助于验证软件的正确性并防止缺陷。这在大规模应用中尤其有价值。 22 | 23 | TypeScript 的一些好处 24 | 25 | * 静态类型,可选强类型 26 | * 类型推断 27 | * 能使用ES6和ES7的新功能 28 | * 跨平台和跨浏览器兼容性 \* IntelliSense 工具支持 29 | 30 | ### TypeScript 和 JavaScript 31 | 32 | TypeScript是用`.ts`或`.tsx`文件编写的, 而JavaScript是用`.js`或`.jsx`文件编写的。 33 | 34 | 扩展名为.tsx或.jsx的文件可以包含 JavaScript 语法扩展 JSX,该扩展在 React 中用于 UI 开发。 35 | 36 | 就语法而言,TypeScript 是 JavaScript (ECMAScript 2015) 的类型化超集。所有 JavaScript 代码都是有效的 TypeScript 代码,但反之则不然。 37 | 38 | 例如,考虑 JavaScript 文件中具有.js扩展名的函数,如下所示: 39 | 40 | 41 | ```typescript 42 | const sum = (a, b) => a + b; 43 | ``` 44 | 45 | 该函数可以通过将文件扩展名更改为 .TypeScript 来转换和使用.ts。但是,如果同一个函数使用 TypeScript 类型进行注释,则未经编译就无法在任何 JavaScript 运行时中执行。如果未编译以下 TypeScript 代码,将会产生语法错误 46 | 47 | 48 | ```typescript 49 | const sum = (a: number, b: number): number => a + b; 50 | ``` 51 | 52 | TypeScript 旨在通过让开发人员使用类型注释定义意图来检测编译期间运行时可能发生的异常。此外,如果没有提供类型注释,TypeScript 也可以捕获问题。例如,以下代码片段未指定任何 TypeScript 类型: 53 | 54 | 55 | ```typescript 56 | const items = [{ x: 1 }, { x: 2 }]; 57 | const result = items.filter(item => item.y); 58 | ``` 59 | 60 | 在这种情况下,TypeScript 检测到错误并报告: 61 | 62 | ```text 63 | 类型 '{ x: number; }' 上不存在属性 'y' 。 64 | ``` 65 | 66 | TypeScript 的类型系统很大程度上受到 JavaScript 运行时行为的影响。例如,加法运算符 (+) 在 JavaScript 中可以执行字符串连接或数字加法,在 TypeScript 中以相同的方式建模: 67 | 68 | ```typescript 69 | const result = '1' + 1; // 结果是string类型 70 | ``` 71 | 72 | TypeScript 背后的团队经过深思熟虑,决定将 JavaScript 的异常使用标记为错误。例如,考虑以下有效的 JavaScript 代码: 73 | 74 | 75 | ```typescript 76 | const result = 1 + true; // 在JavaScript中, 结果等于2 77 | ``` 78 | 79 | 但是,TypeScript 会抛出错误: 80 | 81 | ```text 82 | 运算符"+"不能应用于类型"number"和"boolean"。 83 | `````` 84 | 85 | 出现此错误的原因是 TypeScript 严格强制执行类型兼容性,在这种情况下,它标识了数字和布尔值之间的无效操作。 86 | 87 | ### TypeScript 代码生成 88 | 89 | TypeScript 编译器有两个主要职责:检查类型错误和编译为 JavaScript。这两个过程是相互独立的。类型不会影响 JavaScript 运行时中代码的执行,因为它们在编译过程中会被完全擦除。即使存在类型错误,TypeScript 仍然可以输出 JavaScript。以下是存在类型错误的 TypeScript 代码示例: 90 | 91 | 92 | ```typescript 93 | const add = (a: number, b: number): number => a + b; 94 | const result = add('x', 'y'); // "字符串"类型的参数不可赋值给"数字"类型的参数 95 | ``` 96 | 97 | 但是,它仍然可以生成可执行的 JavaScript 输出: 98 | 99 | 100 | ```typescript 101 | 'use strict'; 102 | const add = (a, b) => a + b; 103 | const result = add('x', 'y'); // xy 104 | ``` 105 | 106 | 无法在运行时检查 TypeScript 类型。例如: 107 | 108 | 109 | ```typescript 110 | interface Animal { 111 | name: string; 112 | } 113 | interface Dog extends Animal { 114 | bark: () => void; 115 | } 116 | interface Cat extends Animal { 117 | meow: () => void; 118 | } 119 | const makeNoise = (animal: Animal) => { 120 | if (animal instanceof Dog) { 121 | // "Dog"仅指一种类型,但在这里用作值。 122 | // ... 123 | } 124 | }; 125 | ``` 126 | 127 | 由于编译后类型被删除,因此无法在 JavaScript 中运行此代码。为了在运行时识别类型,我们需要使用另一种机制。TypeScript 提供了多种选项,其中常见的一个是 "标签联合(tagged union)"。例如: 128 | 129 | ```typescript 130 | interface Dog { 131 | kind: 'dog'; // 标签联合 132 | bark: () => void; 133 | } 134 | interface Cat { 135 | kind: 'cat'; // 标签联合 136 | meow: () => void; 137 | } 138 | type Animal = Dog | Cat; 139 | 140 | const makeNoise = (animal: Animal) => { 141 | if (animal.kind === 'dog') { 142 | animal.bark(); 143 | } else { 144 | animal.meow(); 145 | } 146 | }; 147 | 148 | const dog: Dog = { 149 | kind: 'dog', 150 | bark: () => console.log('bark'), 151 | }; 152 | makeNoise(dog); 153 | ``` 154 | 155 | 属性"kind"是一个可以在运行时用来区分 JavaScript 中的对象的值。 156 | 157 | 运行时的值也可能具有与类型声明中声明的类型不同的类型。例如,如果开发人员误解了 API 类型并对其进行了错误注释。 158 | 159 | TypeScript 是 JavaScript 的超集,因此"class"关键字可以在运行时用作类型和值。 160 | 161 | ```typescript 162 | class Animal { 163 | constructor(public name: string) {} 164 | } 165 | class Dog extends Animal { 166 | constructor(public name: string, public bark: () => void) { 167 | super(name); 168 | } 169 | } 170 | class Cat extends Animal { 171 | constructor(public name: string, public meow: () => void) { 172 | super(name); 173 | } 174 | } 175 | type Mammal = Dog | Cat; 176 | 177 | const makeNoise = (mammal: Mammal) => { 178 | if (mammal instanceof Dog) { 179 | mammal.bark(); 180 | } else { 181 | mammal.meow(); 182 | } 183 | }; 184 | 185 | const dog = new Dog('Fido', () => console.log('bark')); 186 | makeNoise(dog); 187 | ``` 188 | 189 | 在 JavaScript 中,"类"具有"prototype"属性,"instanceof"运算符可用于测试构造函数的原型属性是否出现在对象原型链中的任何位置。 190 | 191 | TypeScript 对运行时性能没有影响,因为所有类型都将被删除。然而,TypeScript 确实引入了一些构建时间开销。 192 | 193 | ### 现在的现代 JavaScript(降级) 194 | 195 | TypeScript 可以将代码编译为自 ECMAScript 3 (1999) 以来任何已发布的 JavaScript 版本。这意味着 TypeScript 可以将代码从最新的 JavaScript 功能转换为旧版本,这一过程称为降级。这允许使用现代 JavaScript,同时保持与旧运行时环境的最大兼容性。 196 | 197 | 值得注意的是,在转换为旧版本 JavaScript 的过程中,TypeScript 可能会生成与本机实现相比会产生性能开销的代码。 198 | 199 | 以下是一些可以在 TypeScript 中使用的现代 JavaScript 功能: 200 | 201 | * ECMAScript 模块,而不是 AMD 风格的"define"回调或 CommonJS 的"require"语句。 202 | * 用类代替原型。 203 | * 变量声明使用"let"或"const"而不是"var"。 204 | * "for-of"循环或".forEach"而不是传统的"for"循环。 205 | * 用箭头函数代替函数表达式。 206 | * 解构赋值。 207 | * 简写属性/方法名称和计算属性名称。 208 | * 默认函数参数。 209 | 210 | 通过利用这些现代 JavaScript 功能,开发人员可以在 TypeScript 中编写更具表现力和简洁的代码。 211 | 212 | -------------------------------------------------------------------------------- /website/src/content/docs/book/table-of-contents.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Table of Contents 3 | sidebar: 4 | order: 4 5 | label: 4. Table of Contents 6 | --- 7 | 8 | 9 | 10 | - The Concise TypeScript Book 11 | - Translations 12 | - Downloads and website 13 | - Table of Contents 14 | - Introduction 15 | - About the Author 16 | - TypeScript Introduction 17 | - What is TypeScript? 18 | - Why TypeScript? 19 | - TypeScript and JavaScript 20 | - TypeScript Code Generation 21 | - Modern JavaScript Now (Downleveling) 22 | - Getting Started With TypeScript 23 | - Installation 24 | - Configuration 25 | - TypeScript Configuration File 26 | - target 27 | - lib 28 | - strict 29 | - module 30 | - moduleResolution 31 | - esModuleInterop 32 | - jsx 33 | - skipLibCheck 34 | - files 35 | - include 36 | - exclude 37 | - importHelpers 38 | - Migration to TypeScript Advice 39 | - Exploring the Type System 40 | - The TypeScript Language Service 41 | - Structural Typing 42 | - TypeScript Fundamental Comparison Rules 43 | - Types as Sets 44 | - Assign a type: Type Declarations and Type Assertions 45 | - Type Declaration 46 | - Type Assertion 47 | - Ambient Declarations 48 | - Property Checking and Excess Property Checking 49 | - Weak Types 50 | - Strict Object Literal Checking (Freshness) 51 | - Type Inference 52 | - More Advanced Inferences 53 | - Type Widening 54 | - Const 55 | - Const Modifier on Type Parameters 56 | - Const assertion 57 | - Explicit Type Annotation 58 | - Type Narrowing 59 | - Conditions 60 | - Throwing or returning 61 | - Discriminated Union 62 | - User-Defined Type Guards 63 | - Primitive Types 64 | - string 65 | - boolean 66 | - number 67 | - bigInt 68 | - Symbol 69 | - null and undefined 70 | - Array 71 | - any 72 | - Type Annotations 73 | - Optional Properties 74 | - Readonly Properties 75 | - Index Signatures 76 | - Extending Types 77 | - Literal Types 78 | - Literal Inference 79 | - strictNullChecks 80 | - Enums 81 | - Numeric enums 82 | - String enums 83 | - Constant enums 84 | - Reverse mapping 85 | - Ambient enums 86 | - Computed and constant members 87 | - Narrowing 88 | - typeof type guards 89 | - Truthiness narrowing 90 | - Equality narrowing 91 | - In Operator narrowing 92 | - instanceof narrowing 93 | - Assignments 94 | - Control Flow Analysis 95 | - Type Predicates 96 | - Discriminated Unions 97 | - The never Type 98 | - Exhaustiveness checking 99 | - Object Types 100 | - Tuple Type (Anonymous) 101 | - Named Tuple Type (Labeled) 102 | - Fixed Length Tuple 103 | - Union Type 104 | - Intersection Types 105 | - Type Indexing 106 | - Type from Value 107 | - Type from Func Return 108 | - Type from Module 109 | - Mapped Types 110 | - Mapped Type Modifiers 111 | - Conditional Types 112 | - Distributive Conditional Types 113 | - infer Type Inference in Conditional Types 114 | - Predefined Conditional Types 115 | - Template Union Types 116 | - Any type 117 | - Unknown type 118 | - Void type 119 | - Never type 120 | - Interface and Type 121 | - Common Syntax 122 | - Basic Types 123 | - Objects and Interfaces 124 | - Union and Intersection Types 125 | - Built-in Type Primitives 126 | - Common Built-in JS Objects 127 | - Overloads 128 | - Merging and Extension 129 | - Differences between Type and Interface 130 | - Class 131 | - Class Common Syntax 132 | - Constructor 133 | - Private and Protected Constructors 134 | - Access Modifiers 135 | - Get and Set 136 | - Auto-Accessors in Classes 137 | - this 138 | - Parameter Properties 139 | - Abstract Classes 140 | - With Generics 141 | - Decorators 142 | - Class Decorators 143 | - Property Decorator 144 | - Method Decorator 145 | - Getter and Setter Decorators 146 | - Decorator Metadata 147 | - Inheritance 148 | - Statics 149 | - Property initialization 150 | - Method overloading 151 | - Generics 152 | - Generic Type 153 | - Generic Classes 154 | - Generic Constraints 155 | - Generic contextual narrowing 156 | - Erased Structural Types 157 | - Namespacing 158 | - Symbols 159 | - Triple-Slash Directives 160 | - Type Manipulation 161 | - Creating Types from Types 162 | - Indexed Access Types 163 | - Utility Types 164 | - Awaited\ 165 | - Partial\ 166 | - Required\ 167 | - Readonly\ 168 | - Record\ 169 | - Pick\ 170 | - Omit\ 171 | - Exclude\ 172 | - Extract\ 173 | - NonNullable\ 174 | - Parameters\ 175 | - ConstructorParameters\ 176 | - ReturnType\ 177 | - InstanceType\ 178 | - ThisParameterType\ 179 | - OmitThisParameter\ 180 | - ThisType\ 181 | - Uppercase\ 182 | - Lowercase\ 183 | - Capitalize\ 184 | - Uncapitalize\ 185 | - NoInfer\ 186 | - Others 187 | - Errors and Exception Handling 188 | - Mixin classes 189 | - Asynchronous Language Features 190 | - Iterators and Generators 191 | - TsDocs JSDoc Reference 192 | - @types 193 | - JSX 194 | - ES6 Modules 195 | - ES7 Exponentiation Operator 196 | - The for-await-of Statement 197 | - New target meta-property 198 | - Dynamic Import Expressions 199 | - "tsc –watch" 200 | - Non-null Assertion Operator 201 | - Defaulted declarations 202 | - Optional Chaining 203 | - Nullish coalescing operator 204 | - Template Literal Types 205 | - Function overloading 206 | - Recursive Types 207 | - Recursive Conditional Types 208 | - ECMAScript Module Support in Node 209 | - Assertion Functions 210 | - Variadic Tuple Types 211 | - Boxed types 212 | - Covariance and Contravariance in TypeScript 213 | - Optional Variance Annotations for Type Parameters 214 | - Template String Pattern Index Signatures 215 | - The satisfies Operator 216 | - Type-Only Imports and Export 217 | - using declaration and Explicit Resource Management 218 | - await using declaration 219 | - Import Attributes 220 | 221 | 222 | -------------------------------------------------------------------------------- /website/src/content/docs/zh-cn/book/type-manipulation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 类型操作 3 | sidebar: 4 | order: 60 5 | label: 60. 类型操作 6 | --- 7 | 8 | 9 | ### 从类型创建类型 10 | 11 | 是否可以通过组合、操作或转换现有类型来创建新类型。 12 | 13 | 交集类型 ( &): 14 | 15 | 允许您将多种类型组合成单一类型: 16 | 17 | ```typescript 18 | type A = { foo: number }; 19 | type B = { bar: string }; 20 | type C = A & B; // A和B的交集 21 | const obj: C = { foo: 42, bar: 'hello' }; 22 | ``` 23 | 24 | 联合类型 (`|`): 25 | 26 | 允许您定义可以是以下几种类型之一的类型 27 | 28 | ```typescript 29 | type Result = string | number; 30 | const value1: Result = 'hello'; 31 | const value2: Result = 42; 32 | ``` 33 | 34 | 映射类型: 35 | 36 | 允许您转换现有类型的属性以创建新类型: 37 | 38 | ```typescript 39 | type Mutable = { 40 | readonly [P in keyof T]: T[P]; 41 | }; 42 | type Person = { 43 | name: string; 44 | age: number; 45 | }; 46 | type ImmutablePerson = Mutable; // 属性变为只读 47 | ``` 48 | 49 | 条件类型: 50 | 51 | 允许您根据某些条件创建类型: 52 | 53 | ```typescript 54 | type ExtractParam = T extends (param: infer P) => any ? P : never; 55 | type MyFunction = (name: string) => number; 56 | type ParamType = ExtractParam; // string 57 | ``` 58 | 59 | ### 索引访问类型 60 | 61 | 在 TypeScript 中,可以使用索引访问和操作另一个类型中的属性类型 `Type[Key]`。 62 | 63 | ```typescript 64 | type Person = { 65 | name: string; 66 | age: number; 67 | }; 68 | 69 | type AgeType = Person['age']; // number 70 | ``` 71 | 72 | ```typescript 73 | type MyTuple = [string, number, boolean]; 74 | type MyType = MyTuple[2]; // boolean 75 | ``` 76 | 77 | ### 工具类型 78 | 79 | 可以使用几种内置工具来操作类型,下面列出了最常用的: 80 | 81 | #### Awaited\ 82 | 83 | 构造一个递归解包 Promise 类型的类型。 84 | 85 | ```typescript 86 | type A = Awaited>; // string 87 | ``` 88 | 89 | #### Partial\ 90 | 91 | 构造一个类型,并将 T 的所有属性设置为可选。 92 | 93 | ```typescript 94 | type Person = { 95 | name: string; 96 | age: number; 97 | }; 98 | 99 | type A = Partial; // { name?: string | undefined; age?: number | undefined; } 100 | ``` 101 | 102 | #### Required\ 103 | 104 | 构造一个类型,并将 T 的所有属性设置为必需。 105 | 106 | ```typescript 107 | type Person = { 108 | name?: string; 109 | age?: number; 110 | }; 111 | 112 | type A = Required; // { name: string; age: number; } 113 | ``` 114 | 115 | #### Readonly\ 116 | 117 | 构造一个类型,并将 T 的所有属性设置为只读。 118 | 119 | 120 | ```typescript 121 | type Person = { 122 | name: string; 123 | age: number; 124 | }; 125 | 126 | type A = Readonly; 127 | 128 | const a: A = { name: 'Simon', age: 17 }; 129 | a.name = 'John'; // 无效 130 | ``` 131 | 132 | #### Record\ 133 | 134 | 构造一个具有类型 T 的一组属性 K 的类型。 135 | 136 | ```typescript 137 | type Product = { 138 | name: string; 139 | price: number; 140 | }; 141 | 142 | const products: Record = { 143 | apple: { name: 'Apple', price: 0.5 }, 144 | banana: { name: 'Banana', price: 0.25 }, 145 | }; 146 | 147 | console.log(products.apple); // { name: 'Apple', price: 0.5 } 148 | ``` 149 | 150 | #### Pick\ 151 | 152 | 通过从 T 中选取指定属性 K 来构造类型。 153 | 154 | ```typescript 155 | type Product = { 156 | name: string; 157 | price: number; 158 | }; 159 | 160 | type Price = Pick; // { price: number; } 161 | ``` 162 | 163 | #### Omit\ 164 | 165 | 通过从 T 中省略指定属性 K 来构造类型。 166 | 167 | ```typescript 168 | type Product = { 169 | name: string; 170 | price: number; 171 | }; 172 | 173 | type Name = Omit; // { name: string; } 174 | ``` 175 | 176 | #### Exclude\ 177 | 178 | 通过从 T 中排除类型 U 的所有值来构造类型。 179 | 180 | ```typescript 181 | type Union = 'a' | 'b' | 'c'; 182 | type MyType = Exclude; // b 183 | ``` 184 | 185 | #### Extract\ 186 | 187 | 通过从 T 中提取类型 U 的所有值来构造类型。 188 | 189 | ```typescript 190 | type Union = 'a' | 'b' | 'c'; 191 | type MyType = Extract; // a | c 192 | ``` 193 | 194 | #### NonNullable\ 195 | 196 | 通过从 T 中排除 null 和 undefined 来构造类型。 197 | 198 | ```typescript 199 | type Union = 'a' | null | undefined | 'b'; 200 | type MyType = NonNullable; // 'a' | 'b' 201 | ``` 202 | 203 | #### Parameters\ 204 | 205 | 提取函数类型 T 的参数类型。 206 | 207 | ```typescript 208 | type Func = (a: string, b: number) => void; 209 | type MyType = Parameters; // [a: string, b: number] 210 | ``` 211 | 212 | #### ConstructorParameters\ 213 | 214 | 提取构造函数类型 T 的参数类型。 215 | 216 | ```typescript 217 | class Person { 218 | constructor( 219 | public name: string, 220 | public age: number 221 | ) {} 222 | } 223 | type PersonConstructorParams = ConstructorParameters; // [name: string, age: number] 224 | const params: PersonConstructorParams = ['John', 30]; 225 | const person = new Person(...params); 226 | console.log(person); // Person { name: 'John', age: 30 } 227 | ``` 228 | 229 | #### ReturnType\ 230 | 231 | 提取函数类型 T 的返回类型。 232 | 233 | ```typescript 234 | type Func = (name: string) => number; 235 | type MyType = ReturnType; // number 236 | ``` 237 | 238 | #### InstanceType\ 239 | 240 | 提取类类型 T 的实例类型。 241 | 242 | ```typescript 243 | class Person { 244 | name: string; 245 | 246 | constructor(name: string) { 247 | this.name = name; 248 | } 249 | 250 | sayHello() { 251 | console.log(`Hello, my name is ${this.name}!`); 252 | } 253 | } 254 | 255 | type PersonInstance = InstanceType; 256 | 257 | const person: PersonInstance = new Person('John'); 258 | 259 | person.sayHello(); // Hello, my name is John! 260 | ``` 261 | 262 | #### ThisParameterType\ 263 | 264 | 从函数类型 T 中提取"this"参数的类型。 265 | 266 | ```typescript 267 | interface Person { 268 | name: string; 269 | greet(this: Person): void; 270 | } 271 | type PersonThisType = ThisParameterType; // Person 272 | ``` 273 | 274 | #### OmitThisParameter\ 275 | 276 | 从函数类型 T 中删除"this"参数。 277 | 278 | ```typescript 279 | function capitalize(this: String) { 280 | return this[0].toUpperCase + this.substring(1).toLowerCase(); 281 | } 282 | 283 | type CapitalizeType = OmitThisParameter; // () => string 284 | ``` 285 | 286 | #### ThisType\ 287 | 288 | 作为上下文类型 `this` 的一部分。 289 | 290 | 291 | ```typescript 292 | type Logger = { 293 | log: (error: string) => void; 294 | }; 295 | 296 | let helperFunctions: { [name: string]: Function } & ThisType = { 297 | hello: function () { 298 | this.log('some error'); // 有效,因为"log"是"this"的一部分 299 | this.update(); // 无效 300 | }, 301 | }; 302 | ``` 303 | 304 | #### Uppercase\ 305 | 306 | 将输入类型 T 的名称设为大写。 307 | 308 | ```typescript 309 | type MyType = Uppercase<'abc'>; // "ABC" 310 | ``` 311 | 312 | #### Lowercase\ 313 | 314 | 将输入类型 T 的名称设为小写。 315 | 316 | ```typescript 317 | type MyType = Lowercase<'ABC'>; // "abc" 318 | ``` 319 | 320 | #### Capitalize\ 321 | 322 | 输入类型 T 的名称大写。 323 | 324 | ```typescript 325 | type MyType = Capitalize<'abc'>; // "Abc" 326 | ``` 327 | 328 | #### Uncapitalize\ 329 | 330 | 将输入类型 T 的名称取消大写。 331 | 332 | ```typescript 333 | type MyType = Uncapitalize<'Abc'>; // "abc" 334 | ``` 335 | 336 | #### NoInfer\ 337 | 338 | NoInfer 是一种实用类型,旨在阻止泛型函数范围内类型的自动推断。 339 | 340 | 示例: 341 | 342 | ```typescript 343 | // 泛型函数范围内类型的自动推断。 344 | function fn(x: T[], y: T) { 345 | return x.concat(y); 346 | } 347 | const r = fn(['a', 'b'], 'c'); // 此处的类型为 ("a" | "b" | "c")[] 348 | ``` 349 | 350 | 使用 NoInfer: 351 | 352 | 353 | ```typescript 354 | // 使用 NoInfer 阻止类型推断的示例函数 355 | function fn2(x: T[], y: NoInfer) { 356 | return x.concat(y); 357 | } 358 | 359 | const r2 = fn2(["a", "b"], "c"); // 错误:类型为“c”的类型参数不能分配给类型为“a”|“b”的参数。 360 | ``` 361 | 362 | -------------------------------------------------------------------------------- /website/src/content/docs/book/type-manipulation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Type Manipulation 3 | sidebar: 4 | order: 60 5 | label: 60. Type Manipulation 6 | --- 7 | 8 | 9 | ### Creating Types from Types 10 | 11 | Is it possible to create new types composing, manipulating or transforming existing types. 12 | 13 | Intersection Types (`&`): 14 | 15 | Allow you to combine multiple types into a single type: 16 | 17 | ```typescript 18 | type A = { foo: number }; 19 | type B = { bar: string }; 20 | type C = A & B; // Intersection of A and B 21 | const obj: C = { foo: 42, bar: 'hello' }; 22 | ``` 23 | 24 | Union Types (`|`): 25 | 26 | Allow you to define a type that can be one of several types: 27 | 28 | ```typescript 29 | type Result = string | number; 30 | const value1: Result = 'hello'; 31 | const value2: Result = 42; 32 | ``` 33 | 34 | Mapped Types: 35 | 36 | Allow you to transform the properties of an existing type to create new type: 37 | 38 | ```typescript 39 | type Mutable = { 40 | readonly [P in keyof T]: T[P]; 41 | }; 42 | type Person = { 43 | name: string; 44 | age: number; 45 | }; 46 | type ImmutablePerson = Mutable; // Properties become read-only 47 | ``` 48 | 49 | Conditional types: 50 | 51 | Allow you to create types based on some conditions: 52 | 53 | ```typescript 54 | type ExtractParam = T extends (param: infer P) => any ? P : never; 55 | type MyFunction = (name: string) => number; 56 | type ParamType = ExtractParam; // string 57 | ``` 58 | 59 | ### Indexed Access Types 60 | 61 | In TypeScript is it possible to access and manipulate the types of properties within another type using an index, `Type[Key]`. 62 | 63 | ```typescript 64 | type Person = { 65 | name: string; 66 | age: number; 67 | }; 68 | 69 | type AgeType = Person['age']; // number 70 | ``` 71 | 72 | ```typescript 73 | type MyTuple = [string, number, boolean]; 74 | type MyType = MyTuple[2]; // boolean 75 | ``` 76 | 77 | ### Utility Types 78 | 79 | Several built-in utility types can be used to manipulate types, below a list of the most common used: 80 | 81 | #### Awaited\ 82 | 83 | Constructs a type that recursively unwraps Promise types. 84 | 85 | ```typescript 86 | type A = Awaited>; // string 87 | ``` 88 | 89 | #### Partial\ 90 | 91 | Constructs a type with all properties of T set to optional. 92 | 93 | ```typescript 94 | type Person = { 95 | name: string; 96 | age: number; 97 | }; 98 | 99 | type A = Partial; // { name?: string | undefined; age?: number | undefined; } 100 | ``` 101 | 102 | #### Required\ 103 | 104 | Constructs a type with all properties of T set to required. 105 | 106 | ```typescript 107 | type Person = { 108 | name?: string; 109 | age?: number; 110 | }; 111 | 112 | type A = Required; // { name: string; age: number; } 113 | ``` 114 | 115 | #### Readonly\ 116 | 117 | Constructs a type with all properties of T set to readonly. 118 | 119 | 120 | ```typescript 121 | type Person = { 122 | name: string; 123 | age: number; 124 | }; 125 | 126 | type A = Readonly; 127 | 128 | const a: A = { name: 'Simon', age: 17 }; 129 | a.name = 'John'; // Invalid 130 | ``` 131 | 132 | #### Record\ 133 | 134 | Constructs a type with a set of properties K of type T. 135 | 136 | ```typescript 137 | type Product = { 138 | name: string; 139 | price: number; 140 | }; 141 | 142 | const products: Record = { 143 | apple: { name: 'Apple', price: 0.5 }, 144 | banana: { name: 'Banana', price: 0.25 }, 145 | }; 146 | 147 | console.log(products.apple); // { name: 'Apple', price: 0.5 } 148 | ``` 149 | 150 | #### Pick\ 151 | 152 | Constructs a type by picking the specified properties K from T. 153 | 154 | ```typescript 155 | type Product = { 156 | name: string; 157 | price: number; 158 | }; 159 | 160 | type Price = Pick; // { price: number; } 161 | ``` 162 | 163 | #### Omit\ 164 | 165 | Constructs a type by omitting the specified properties K from T. 166 | 167 | ```typescript 168 | type Product = { 169 | name: string; 170 | price: number; 171 | }; 172 | 173 | type Name = Omit; // { name: string; } 174 | ``` 175 | 176 | #### Exclude\ 177 | 178 | Constructs a type by excluding all values of type U from T. 179 | 180 | ```typescript 181 | type Union = 'a' | 'b' | 'c'; 182 | type MyType = Exclude; // b 183 | ``` 184 | 185 | #### Extract\ 186 | 187 | Constructs a type by extracting all values of type U from T. 188 | 189 | ```typescript 190 | type Union = 'a' | 'b' | 'c'; 191 | type MyType = Extract; // a | c 192 | ``` 193 | 194 | #### NonNullable\ 195 | 196 | Constructs a type by excluding null and undefined from T. 197 | 198 | ```typescript 199 | type Union = 'a' | null | undefined | 'b'; 200 | type MyType = NonNullable; // 'a' | 'b' 201 | ``` 202 | 203 | #### Parameters\ 204 | 205 | Extracts the parameter types of a function type T. 206 | 207 | ```typescript 208 | type Func = (a: string, b: number) => void; 209 | type MyType = Parameters; // [a: string, b: number] 210 | ``` 211 | 212 | #### ConstructorParameters\ 213 | 214 | Extracts the parameter types of a constructor function type T. 215 | 216 | ```typescript 217 | class Person { 218 | constructor( 219 | public name: string, 220 | public age: number 221 | ) {} 222 | } 223 | type PersonConstructorParams = ConstructorParameters; // [name: string, age: number] 224 | const params: PersonConstructorParams = ['John', 30]; 225 | const person = new Person(...params); 226 | console.log(person); // Person { name: 'John', age: 30 } 227 | ``` 228 | 229 | #### ReturnType\ 230 | 231 | Extracts the return type of a function type T. 232 | 233 | ```typescript 234 | type Func = (name: string) => number; 235 | type MyType = ReturnType; // number 236 | ``` 237 | 238 | #### InstanceType\ 239 | 240 | Extracts the instance type of a class type T. 241 | 242 | ```typescript 243 | class Person { 244 | name: string; 245 | 246 | constructor(name: string) { 247 | this.name = name; 248 | } 249 | 250 | sayHello() { 251 | console.log(`Hello, my name is ${this.name}!`); 252 | } 253 | } 254 | 255 | type PersonInstance = InstanceType; 256 | 257 | const person: PersonInstance = new Person('John'); 258 | 259 | person.sayHello(); // Hello, my name is John! 260 | ``` 261 | 262 | #### ThisParameterType\ 263 | 264 | Extracts the type of 'this' parameter from a function type T. 265 | 266 | ```typescript 267 | interface Person { 268 | name: string; 269 | greet(this: Person): void; 270 | } 271 | type PersonThisType = ThisParameterType; // Person 272 | ``` 273 | 274 | #### OmitThisParameter\ 275 | 276 | Removes the 'this' parameter from a function type T. 277 | 278 | ```typescript 279 | function capitalize(this: String) { 280 | return this[0].toUpperCase + this.substring(1).toLowerCase(); 281 | } 282 | 283 | type CapitalizeType = OmitThisParameter; // () => string 284 | ``` 285 | 286 | #### ThisType\ 287 | 288 | Servers as a market for a contextual `this` type. 289 | 290 | 291 | ```typescript 292 | type Logger = { 293 | log: (error: string) => void; 294 | }; 295 | 296 | let helperFunctions: { [name: string]: Function } & ThisType = { 297 | hello: function () { 298 | this.log('some error'); // Valid as "log" is a part of "this". 299 | this.update(); // Invalid 300 | }, 301 | }; 302 | ``` 303 | 304 | #### Uppercase\ 305 | 306 | Make uppercase the name of the input type T. 307 | 308 | ```typescript 309 | type MyType = Uppercase<'abc'>; // "ABC" 310 | ``` 311 | 312 | #### Lowercase\ 313 | 314 | Make lowercase the name of the input type T. 315 | 316 | ```typescript 317 | type MyType = Lowercase<'ABC'>; // "abc" 318 | ``` 319 | 320 | #### Capitalize\ 321 | 322 | Capitalize the name of the input type T. 323 | 324 | ```typescript 325 | type MyType = Capitalize<'abc'>; // "Abc" 326 | ``` 327 | 328 | #### Uncapitalize\ 329 | 330 | Uncapitalize the name of the input type T. 331 | 332 | ```typescript 333 | type MyType = Uncapitalize<'Abc'>; // "abc" 334 | ``` 335 | 336 | #### NoInfer\ 337 | 338 | NoInfer is a utility type designed to block the automatic inference of types within the scope of a generic function. 339 | 340 | Example: 341 | 342 | ```typescript 343 | // Automatic inference of types within the scope of a generic function. 344 | function fn(x: T[], y: T) { 345 | return x.concat(y); 346 | } 347 | const r = fn(['a', 'b'], 'c'); // Type here is ("a" | "b" | "c")[] 348 | ``` 349 | 350 | With NoInfer: 351 | 352 | 353 | ```typescript 354 | // Example function that uses NoInfer to prevent type inference 355 | function fn2(x: T[], y: NoInfer) { 356 | return x.concat(y); 357 | } 358 | 359 | const r2 = fn2(['a', 'b'], 'c'); // Error: Type Argument of type '"c"' is not assignable to parameter of type '"a" | "b"'. 360 | ``` 361 | 362 | -------------------------------------------------------------------------------- /website/src/content/docs/book/typescript-introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: TypeScript Introduction 3 | sidebar: 4 | order: 7 5 | label: 7. TypeScript Introduction 6 | --- 7 | 8 | 9 | ### What is TypeScript? 10 | 11 | TypeScript is a strongly typed programming language that builds on JavaScript. It was originally designed by Anders Hejlsberg in 2012 and is currently developed and maintained by Microsoft as an open source project. 12 | 13 | TypeScript compiles to JavaScript and can be executed in any JavaScript runtime (e.g., a browser or server Node.js). 14 | 15 | TypeScript supports multiple programming paradigms such as functional, generic, imperative, and object-oriented. TypeScript is neither an interpreted nor a compiled language. 16 | 17 | ### Why TypeScript? 18 | 19 | TypeScript is a strongly typed language that helps prevent common programming mistakes and avoid certain kinds of run-time errors before the program is executed. 20 | 21 | A strongly typed language allows the developer to specify various program constraints and behaviors in the data type definitions, facilitating the ability to verify the correctness of the software and prevent defects. This is especially valuable in large-scale applications. 22 | 23 | Some of the benefits of TypeScript: 24 | 25 | * Static typing, optionally strongly typed 26 | * Type Inference 27 | * Access to ES6 and ES7 features 28 | * Cross-Platform and Cross-browser Compatibility 29 | * Tooling support with IntelliSense 30 | 31 | ### TypeScript and JavaScript 32 | 33 | TypeScript is written in `.ts` or `.tsx` files, while JavaScript files are written in `.js` or `.jsx`. 34 | 35 | Files with the extension `.tsx` or `.jsx` can contain JavaScript Syntax Extension JSX, which is used in React for UI development. 36 | 37 | TypeScript is a typed superset of JavaScript (ECMAScript 2015) in terms of syntax. All JavaScript code is valid TypeScript code, but the reverse is not always true. 38 | 39 | For instance, consider a function in a JavaScript file with the `.js` extension, such as the following: 40 | 41 | 42 | ```typescript 43 | const sum = (a, b) => a + b; 44 | ``` 45 | 46 | The function can be converted and used in TypeScript by changing the file extension to `.ts`. However, if the same function is annotated with TypeScript types, it cannot be executed in any JavaScript runtime without compilation. The following TypeScript code will produce a syntax error if it is not compiled: 47 | 48 | 49 | ```typescript 50 | const sum = (a: number, b: number): number => a + b; 51 | ``` 52 | 53 | TypeScript was designed to detect possible exceptions that can occur at runtime during compilation time by having the developer define the intent with type annotations. In addition, TypeScript can also catch issues if no type annotation is provided. For instance, the following code snippet does not specify any TypeScript types: 54 | 55 | 56 | ```typescript 57 | const items = [{ x: 1 }, { x: 2 }]; 58 | const result = items.filter(item => item.y); 59 | ``` 60 | 61 | In this case, TypeScript detects an error and reports: 62 | 63 | ```text 64 | Property 'y' does not exist on type '{ x: number; }'. 65 | ``` 66 | 67 | TypeScript's type system is largely influenced by the runtime behavior of JavaScript. For example, the addition operator (+), which in JavaScript can either perform string concatenation or numeric addition, is modeled in the same way in TypeScript: 68 | 69 | ```typescript 70 | const result = '1' + 1; // Result is of type string 71 | ``` 72 | 73 | The team behind TypeScript has made a deliberate decision to flag unusual usage of JavaScript as errors. For instance, consider the following valid JavaScript code: 74 | 75 | 76 | ```typescript 77 | const result = 1 + true; // In JavaScript, the result is equal 2 78 | ``` 79 | 80 | However, TypeScript throws an error: 81 | 82 | ```text 83 | Operator '+' cannot be applied to types 'number' and 'boolean'. 84 | ``` 85 | 86 | This error occurs because TypeScript strictly enforces type compatibility, and in this case, it identifies an invalid operation between a number and a boolean. 87 | 88 | ### TypeScript Code Generation 89 | 90 | The TypeScript compiler has two main responsibilities: checking for type errors and compiling to JavaScript. These two processes are independent of each other. Types do not affect the execution of the code in a JavaScript runtime, as they are completely erased during compilation. TypeScript can still output JavaScript even in the presence of type errors. 91 | Here is an example of TypeScript code with a type error: 92 | 93 | 94 | ```typescript 95 | const add = (a: number, b: number): number => a + b; 96 | const result = add('x', 'y'); // Argument of type 'string' is not assignable to parameter of type 'number'. 97 | ``` 98 | 99 | However, it can still produce executable JavaScript output: 100 | 101 | 102 | ```typescript 103 | 'use strict'; 104 | const add = (a, b) => a + b; 105 | const result = add('x', 'y'); // xy 106 | ``` 107 | 108 | It is not possible to check TypeScript types at runtime. For example: 109 | 110 | 111 | ```typescript 112 | interface Animal { 113 | name: string; 114 | } 115 | interface Dog extends Animal { 116 | bark: () => void; 117 | } 118 | interface Cat extends Animal { 119 | meow: () => void; 120 | } 121 | const makeNoise = (animal: Animal) => { 122 | if (animal instanceof Dog) { 123 | // 'Dog' only refers to a type, but is being used as a value here. 124 | // ... 125 | } 126 | }; 127 | ``` 128 | 129 | As the types are erased after compilation, there is no way to run this code in JavaScript. To recognize types at runtime, we need to use another mechanism. TypeScript provides several options, with a common one being "tagged union". For example: 130 | 131 | ```typescript 132 | interface Dog { 133 | kind: 'dog'; // Tagged union 134 | bark: () => void; 135 | } 136 | interface Cat { 137 | kind: 'cat'; // Tagged union 138 | meow: () => void; 139 | } 140 | type Animal = Dog | Cat; 141 | 142 | const makeNoise = (animal: Animal) => { 143 | if (animal.kind === 'dog') { 144 | animal.bark(); 145 | } else { 146 | animal.meow(); 147 | } 148 | }; 149 | 150 | const dog: Dog = { 151 | kind: 'dog', 152 | bark: () => console.log('bark'), 153 | }; 154 | makeNoise(dog); 155 | ``` 156 | 157 | The property "kind" is a value that can be used at runtime to distinguish between objects in JavaScript. 158 | 159 | It is also possible for a value at runtime to have a type different from the one declared in the type declaration. For instance, if the developer has misinterpreted an API type and annotated it incorrectly. 160 | 161 | TypeScript is a superset of JavaScript, so the "class" keyword can be used as a type and value at runtime. 162 | 163 | ```typescript 164 | class Animal { 165 | constructor(public name: string) {} 166 | } 167 | class Dog extends Animal { 168 | constructor( 169 | public name: string, 170 | public bark: () => void 171 | ) { 172 | super(name); 173 | } 174 | } 175 | class Cat extends Animal { 176 | constructor( 177 | public name: string, 178 | public meow: () => void 179 | ) { 180 | super(name); 181 | } 182 | } 183 | type Mammal = Dog | Cat; 184 | 185 | const makeNoise = (mammal: Mammal) => { 186 | if (mammal instanceof Dog) { 187 | mammal.bark(); 188 | } else { 189 | mammal.meow(); 190 | } 191 | }; 192 | 193 | const dog = new Dog('Fido', () => console.log('bark')); 194 | makeNoise(dog); 195 | ``` 196 | 197 | In JavaScript, a "class" has a "prototype" property, and the "instanceof" operator can be used to test if the prototype property of a constructor appears anywhere in the prototype chain of an object. 198 | 199 | TypeScript has no effect on runtime performance, as all types will be erased. However, TypeScript does introduce some build time overhead. 200 | 201 | ### Modern JavaScript Now (Downleveling) 202 | 203 | TypeScript can compile code to any released version of JavaScript since ECMAScript 3 (1999). This means that TypeScript can transpile code from the latest JavaScript features to older versions, a process known as Downleveling. This allows the usage of modern JavaScript while maintaining maximum compatibility with older runtime environments. 204 | 205 | It's important to note that during transpilation to an older version of JavaScript, TypeScript may generate code that could incur a performance overhead compared to native implementations. 206 | 207 | Here are some of the modern JavaScript features that can be used in TypeScript: 208 | 209 | * ECMAScript modules instead of AMD-style "define" callbacks or CommonJS "require" statements. 210 | * Classes instead of prototypes. 211 | * Variables declaration using "let" or "const" instead of "var". 212 | * "for-of" loop or ".forEach" instead of the traditional "for" loop. 213 | * Arrow functions instead of function expressions. 214 | * Destructuring assignment. 215 | * Shorthand property/method names and computed property names. 216 | * Default function parameters. 217 | 218 | By leveraging these modern JavaScript features, developers can write more expressive and concise code in TypeScript. 219 | 220 | -------------------------------------------------------------------------------- /website/src/content/docs/book/getting-started-with-typescript.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Getting Started With TypeScript 3 | sidebar: 4 | order: 8 5 | label: 8. Getting Started With TypeScript 6 | --- 7 | 8 | 9 | ### Installation 10 | 11 | Visual Studio Code provides excellent support for the TypeScript language but does not include the TypeScript compiler. To install the TypeScript compiler, you can use a package manager like npm or yarn: 12 | 13 | ```shell 14 | npm install typescript --save-dev 15 | ``` 16 | 17 | or 18 | 19 | ```shell 20 | yarn add typescript --dev 21 | ``` 22 | 23 | Make sure to commit the generated lockfile to ensure that every team member uses the same version of TypeScript. 24 | 25 | To run the TypeScript compiler, you can use the following commands 26 | 27 | ```shell 28 | npx tsc 29 | ``` 30 | 31 | or 32 | 33 | ```shell 34 | yarn tsc 35 | ``` 36 | 37 | It is recommended to install TypeScript project-wise rather than globally, as it provides a more predictable build process. However, for one-off occasions, you can use the following command: 38 | 39 | ```shell 40 | npx tsc 41 | ``` 42 | 43 | or installing it globally: 44 | 45 | ```shell 46 | npm install -g typescript 47 | ``` 48 | 49 | If you are using Microsoft Visual Studio, you can obtain TypeScript as a package in NuGet for your MSBuild projects. In the NuGet Package Manager Console, run the following command: 50 | 51 | ```shell 52 | Install-Package Microsoft.TypeScript.MSBuild 53 | ``` 54 | 55 | During the TypeScript installation, two executables are installed: "tsc" as the TypeScript compiler and "tsserver" as the TypeScript standalone server. The standalone server contains the compiler and language services that can be utilized by editors and IDEs to provide intelligent code completion. 56 | 57 | Additionally, there are several TypeScript-compatible transpilers available, such as Babel (via a plugin) or swc. These transpilers can be used to convert TypeScript code into other target languages or versions. 58 | 59 | ### Configuration 60 | 61 | TypeScript can be configured using the tsc CLI options or by utilizing a dedicated configuration file called tsconfig.json placed in the root of the project. 62 | 63 | To generate a tsconfig.json file prepopulated with recommended settings, you can use the following command: 64 | 65 | ```shell 66 | tsc --init 67 | ``` 68 | 69 | When executing the `tsc` command locally, TypeScript will compile the code using the configuration specified in the nearest tsconfig.json file. 70 | 71 | Here are some examples of CLI commands that run with the default settings: 72 | 73 | ```shell 74 | tsc main.ts // Compile a specific file (main.ts) to JavaScript 75 | tsc src/*.ts // Compile any .ts files under the 'src' folder to JavaScript 76 | tsc app.ts util.ts --outfile index.js // Compile two TypeScript files (app.ts and util.ts) into a single JavaScript file (index.js) 77 | ``` 78 | 79 | ### TypeScript Configuration File 80 | 81 | A tsconfig.json file is used to configure the TypeScript Compiler (tsc). Usually, it is added to the root of the project, together with the `package.json` file. 82 | 83 | Notes: 84 | 85 | * tsconfig.json accepts comments even if it is in json format. 86 | * It is advisable to use this configuration file instead of the command-line options. 87 | 88 | At the following link you can find the complete documentation and its schema: 89 | 90 | [https://www.typescriptlang.org/tsconfig](https://www.typescriptlang.org/tsconfig) 91 | 92 | [http://json.schemastore.org/tsconfig](http://json.schemastore.org/tsconfig) 93 | 94 | The following represents a list of the common and useful configurations: 95 | 96 | #### target 97 | 98 | The "target" property is used to specify which version of JavaScript ECMAScript version your TypeScript should emit/compile into. For modern browsers ES6 is a good option, for older browsers, ES5 is recommended. 99 | 100 | #### lib 101 | 102 | The "lib" property is used to specify which library files to include at compilation time. TypeScript automatically includes APIs for features specified in the "target" property, but it is possible to omit or pick specific libraries for particular needs. For instance, if you are working on a server project, you could exclude the "DOM" library, which is useful only in a browser environment. 103 | 104 | #### strict 105 | 106 | The "strict" property enables stronger guarantees and enhances type safety. It is advisable to always include this property in your project's tsconfig.json file. Enabling the "strict" property allows TypeScript to: 107 | 108 | * Emit code using "use strict" for each source file. 109 | * Consider "null" and "undefined" in the type checking process. 110 | * Disable the usage of the "any" type when no type annotations are present. 111 | * Raise an error on the usage of the "this" expression, which would otherwise imply the "any" type. 112 | 113 | #### module 114 | 115 | The "module" property sets the module system supported for the compiled program. During runtime, a module loader is used to locate and execute dependencies based on the specified module system. 116 | 117 | The most common module loaders used in JavaScript are Node.js CommonJS for server-side applications and RequireJS for AMD modules in browser-based web applications. TypeScript can emit code for various module systems, including UMD, System, ESNext, ES2015/ES6, and ES2020. 118 | 119 | Note: The module system should be chosen based on the target environment and the module loading mechanism available in that environment. 120 | 121 | #### moduleResolution 122 | 123 | The "moduleResolution" property specifies the module resolution strategy. Use "node" for modern TypeScript code, the "classic" strategy is used only for old versions of TypeScript (before 1.6). 124 | 125 | #### esModuleInterop 126 | 127 | The "esModuleInterop" property allows import default from CommonJS modules that did not export using the "default" property, this property provides a shim to ensure compatibility in the emitted JavaScript. After enabling this option we can use `import MyLibrary from "my-library"` instead of `import * as MyLibrary from "my-library"`. 128 | 129 | #### jsx 130 | 131 | The "jsx" property applies only to .tsx files used in ReactJS and controls how JSX constructs are compiled into JavaScript. A common option is "preserve" which will compile to a .jsx file keeping unchanged the JSX so it can be passed to different tools like Babel for further transformations. 132 | 133 | #### skipLibCheck 134 | 135 | The "skipLibCheck'' property will prevent TypeScript from type-checking the entire imported third-party packages. This property will reduce the compile time of a project. TypeScript will still check your code against the type definitions provided by these packages. 136 | 137 | #### files 138 | 139 | The "files" property indicates to the compiler a list of files that must always be included in the program. 140 | 141 | #### include 142 | 143 | 144 | The "include" property indicates to the compiler a list of files that we would like to include. This property allows glob-like patterns, such as "\*_" for any subdirectory, "_" for any file name, and "?" for optional characters. 145 | 146 | 147 | #### exclude 148 | 149 | The "exclude" property indicates to the compiler a list of files that should not be included in the compilation. This can include files such as "node_modules" or test files. 150 | Note: tsconfig.json allows comments. 151 | 152 | ### importHelpers 153 | 154 | TypeScript uses helper code when generating code for certain advanced or down-leveled JavaScript features. By default, these helpers are duplicated in files using them. The `importHelpers` option imports these helpers from the `tslib` module instead, making the JavaScript output more efficient. 155 | 156 | ### Migration to TypeScript Advice 157 | 158 | For large projects, it is recommended to adopt a gradual transition where TypeScript and JavaScript code will initially coexist. Only small projects can be migrated to TypeScript in one go. 159 | 160 | The first step of this transition is to introduce TypeScript into the build chain process. This can be done by using the "allowJs" compiler option, which permits .ts and .tsx files to coexist with existing JavaScript files. As TypeScript will fall back to a type of "any" for a variable when it cannot infer the type from JavaScript files, it is recommended to disable "noImplicitAny" in your compiler options at the beginning of the migration. 161 | 162 | The second step is to ensure that your JavaScript tests work alongside TypeScript files so that you can run tests as you convert each module. If you are using Jest, consider using `ts-jest`, which allows you to test TypeScript projects with Jest. 163 | 164 | The third step is to include type declarations for third-party libraries in your project. These declarations can be found either bundled or on DefinitelyTyped. You can search for them using [https://www.typescriptlang.org/dt/search](https://www.typescriptlang.org/dt/search) and install them using: 165 | 166 | ```shell 167 | npm install --save-dev @types/package-name or yarn add --dev @types/package-name. 168 | ``` 169 | 170 | The fourth step is to migrate module by module with a bottom-up approach, following your Dependency Graph starting with the leaves. The idea is to start converting Modules that do not depend on other Modules. To visualize the dependency graphs, you can use the "madge" tool. 171 | 172 | Good candidate modules for these initial conversions are utility functions and code related to external APIs or specifications. It is possible to automatically generate TypeScript type definitions from Swagger contracts, GraphQL or JSON schemas to be included in your project. 173 | 174 | When there are no specifications or official schemas available, you can generate types from raw data, such as JSON returned by a server. However, it is recommended to generate types from specifications instead of data to avoid missing edge cases. 175 | 176 | During the migration, refrain from code refactoring and focus only on adding types to your modules. 177 | 178 | The fifth step is to enable "noImplicitAny," which will enforce that all types are known and defined, providing a better TypeScript experience for your project. 179 | 180 | During the migration, you can use the `@ts-check` directive, which enables TypeScript type checking in a JavaScript file. This directive provides a loose version of type checking and can be initially used to identify issues in JavaScript files. When `@ts-check` is included in a file, TypeScript will try to deduce definitions using JSDoc-style comments. However, consider using JSDoc annotations only at a very early stage of the migration. 181 | 182 | Consider keeping the default value of `noEmitOnError` in your tsconfig.json as false. This will allow you to output JavaScript source code even if errors are reported. 183 | 184 | --------------------------------------------------------------------------------