├── .editorconfig
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── custom.md
│ └── feature_request.md
└── workflows
│ └── deploy-to-gh-pages.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── commitlint.config.js
├── docs
├── .vuepress
│ ├── components
│ │ ├── Answer.vue
│ │ ├── Editor.vue
│ │ └── MySWUpdatePopup.vue
│ ├── config.js
│ ├── enhanceApp.js
│ ├── public
│ │ ├── images
│ │ │ ├── docs.png
│ │ │ └── icons
│ │ │ │ ├── icon-128x128.png
│ │ │ │ ├── icon-144x144.png
│ │ │ │ ├── icon-152x152.png
│ │ │ │ ├── icon-192x192.png
│ │ │ │ ├── icon-384x384.png
│ │ │ │ ├── icon-512x512.png
│ │ │ │ ├── icon-72x72.png
│ │ │ │ └── icon-96x96.png
│ │ ├── logo.png
│ │ ├── manifest.json
│ │ └── ts-logo.png
│ ├── styles
│ │ └── index.styl
│ └── utils
│ │ ├── alias.json
│ │ ├── copy.js
│ │ ├── nav.js
│ │ ├── plugins.js
│ │ └── sidebarHelper.js
├── README.md
└── zh
│ ├── advanced-types
│ ├── README.md
│ ├── intersection-types
│ │ └── README.md
│ ├── nullable
│ │ └── README.md
│ ├── type-guard
│ │ └── README.md
│ └── union-types
│ │ └── README.md
│ ├── array
│ └── README.md
│ ├── basic
│ └── README.md
│ ├── blog
│ └── README.md
│ ├── built-in-objects
│ └── README.md
│ ├── class
│ └── README.md
│ ├── compile-config
│ ├── README.md
│ ├── file-inclusion
│ │ └── README.md
│ ├── module-resolver
│ │ └── README.md
│ ├── references
│ │ └── README.md
│ └── tsconfig-module-target
│ │ └── README.md
│ ├── declaration
│ └── README.md
│ ├── decorators
│ └── README.md
│ ├── faqs
│ ├── README.md
│ └── interface-vs-type.md
│ ├── function
│ └── README.md
│ ├── generics
│ └── README.md
│ ├── guide
│ └── README.md
│ ├── interface
│ └── README.md
│ ├── keyword
│ ├── README.md
│ ├── as
│ │ └── README.md
│ ├── extends
│ │ └── README.md
│ ├── implements
│ │ └── README.md
│ ├── in
│ │ └── README.md
│ ├── infer
│ │ └── README.md
│ ├── instanceof
│ │ └── README.md
│ ├── is
│ │ └── README.md
│ ├── keyof
│ │ └── README.md
│ └── typeof
│ │ └── README.md
│ ├── operator
│ └── README.md
│ ├── tips
│ ├── README.md
│ ├── if-else
│ │ └── README.md
│ └── spread
│ │ └── README.md
│ ├── type-assertion
│ └── README.md
│ ├── utility-types
│ ├── README.md
│ └── custom-utility-types
│ │ └── README.md
│ └── what-is-typescript
│ ├── README.md
│ └── images
│ └── 2020-ts-download.png
├── how-to-write-docs.md
├── package-lock.json
├── package.json
├── plop-templates
└── README.md.hbs
├── plopfile.js
├── scripts
├── deploy.sh
└── remote.sh
└── wechat-zhifubao-pay.png
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | # https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties
3 |
4 | # 表示是最顶层的配置文件, 发现设为true时, 才会停止查找.editorconfig文件
5 | root = true
6 |
7 | [*]
8 | # tab space
9 | indent_style = tab
10 |
11 | indent_size = 2
12 | # 设置换行符, 值为lf, cr, crlf
13 | end_of_line = lf
14 | charset = utf-8
15 |
16 | # 用一个整数来设置tab缩进的列数。默认是indent_size
17 | tab_width = indent_size
18 |
19 | #是否删除行尾的空格
20 | trim_trailing_whitespace = true
21 |
22 | #是否在文件的最后插入一个空行
23 | insert_final_newline = true
24 |
25 | [*.md]
26 | indent_size = 2
27 | trim_trailing_whitespace = false
28 | insert_final_newline = true
29 |
30 | [Makefile]
31 | indent_style = tab
32 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/custom.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Custom issue template
3 | about: Describe this issue template's purpose here.
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/workflows/deploy-to-gh-pages.yml:
--------------------------------------------------------------------------------
1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
3 |
4 | name: Build and Deploy
5 |
6 | on:
7 | push:
8 | branches: [ master ]
9 | # pull_request:
10 | # branches: [ master ]
11 |
12 | jobs:
13 |
14 | deploy:
15 | runs-on: ubuntu-latest
16 |
17 | steps:
18 | - name: Checkout 🛎️
19 | uses: actions/checkout@master
20 |
21 | - name: Checkout node
22 | uses: actions/setup-node@v4
23 | with:
24 | node-version: 16
25 |
26 | - name: Install and Build 🔧
27 | run: |
28 | # npm ci 依赖 package-lock.json
29 | # npm ci
30 | npm install
31 | npm run docs:build
32 |
33 | - name: Deploy 🚀
34 | uses: JamesIves/github-pages-deploy-action@4.1.1
35 | with:
36 | branch: gh-pages
37 | folder: docs/.vuepress/dist
38 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # IDE & Editor
2 | /.idea/
3 |
4 | # lock file
5 | *lock
6 |
7 |
8 | # Logs
9 | logs
10 | *.log
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | lerna-debug.log*
15 |
16 | # Diagnostic reports (https://nodejs.org/api/report.html)
17 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
18 |
19 | # Runtime data
20 | pids
21 | *.pid
22 | *.seed
23 | *.pid.lock
24 |
25 | # Directory for instrumented libs generated by jscoverage/JSCover
26 | lib-cov
27 |
28 | # Coverage directory used by tools like istanbul
29 | coverage/
30 | *.lcov
31 | .coveralls.yml
32 |
33 | # nyc test coverage
34 | .nyc_output
35 |
36 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
37 | .grunt
38 |
39 | # Bower dependency directory (https://bower.io/)
40 | bower_components
41 |
42 | # node-waf configuration
43 | .lock-wscript
44 |
45 | # Compiled binary addons (https://nodejs.org/api/addons.html)
46 | build/Release
47 |
48 | # Dependency directories
49 | node_modules/
50 | jspm_packages/
51 |
52 | # TypeScript v1 declaration files
53 | typings/
54 |
55 | # TypeScript cache
56 | *.tsbuildinfo
57 |
58 | # Optional npm cache directory
59 | .npm
60 |
61 | # Optional eslint cache
62 | .eslintcache
63 |
64 | # Microbundle cache
65 | .rpt2_cache/
66 | .rts2_cache_cjs/
67 | .rts2_cache_es/
68 | .rts2_cache_umd/
69 |
70 | # Optional REPL history
71 | .node_repl_history
72 |
73 | # Output of 'npm pack'
74 | *.tgz
75 |
76 | # Yarn Integrity file
77 | .yarn-integrity
78 |
79 | # dotenv environment variables file
80 | .env
81 | .env.test
82 |
83 | # parcel-bundler cache (https://parceljs.org/)
84 | .cache
85 |
86 | # Next.js build output
87 | .next
88 |
89 | # Nuxt.js build / generate output
90 | .nuxt
91 | dist
92 |
93 | # Gatsby files
94 | .cache/
95 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
96 | # https://nextjs.org/blog/next-9-1#public-directory-support
97 | # public
98 |
99 | # vuepress build output
100 | .vuepress/dist
101 |
102 | # Serverless directories
103 | .serverless/
104 |
105 | # FuseBox cache
106 | .fusebox/
107 |
108 | # DynamoDB Local files
109 | .dynamodb/
110 |
111 | # TernJS port file
112 | .tern-port
113 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # [1.0.0](https://github.com/Rain120/typescript-guide/compare/0.0.1...1.0.0) (2024-01-16)
2 |
3 |
4 | ### Bug Fixes
5 |
6 | * bug about deploy action folder ([57f4fae](https://github.com/Rain120/typescript-guide/commit/57f4fae89f0f478a51f58c5873936a264e6d4b09))
7 | * bug about deploy action folder(not home ~) ([c4eb45d](https://github.com/Rain120/typescript-guide/commit/c4eb45d079e8fc63ebffd3dca04f5111072da894))
8 | * bug about github actions deploy branch config error ([bc992c0](https://github.com/Rain120/typescript-guide/commit/bc992c05ee17bfcccca14b3400e0e81e9c16c423))
9 | * file inclusion references code ([97806cc](https://github.com/Rain120/typescript-guide/commit/97806ccb834cf0741213da1a496292c7fb301e40))
10 | * github actions deploy bug ([4c64d68](https://github.com/Rain120/typescript-guide/commit/4c64d68ddd17f03a3900219ed06ba453fb25a49f))
11 | * style about deploy with params at yml file ([a4d5ed3](https://github.com/Rain120/typescript-guide/commit/a4d5ed3924239b6498aae6fde169c162123633e7))
12 | * style about deploy with params at yml file ([ddbcee6](https://github.com/Rain120/typescript-guide/commit/ddbcee6fb81af41bcb6528d4db884758c310f476))
13 | * ts operator & chinese anchor bug; type challenges for guide reference ([a441bd5](https://github.com/Rain120/typescript-guide/commit/a441bd541d5a4a33f6228a5c3b50cad51ca8b27f))
14 | * what is typescript for diff with js ([34b01a7](https://github.com/Rain120/typescript-guide/commit/34b01a71712e54e05a973c4b33b68cb5ec7a0b1e))
15 |
16 |
17 | ### Features
18 |
19 | * 工具类型 ([afeb366](https://github.com/Rain120/typescript-guide/commit/afeb366af952d750f012e51fb1c5a33b738f37bd))
20 | * **declaration:** update ([978e800](https://github.com/Rain120/typescript-guide/commit/978e8002c92198ac37a6c09c20c9a6f55bc4145e))
21 | * **extends:** update ([8cd0fdc](https://github.com/Rain120/typescript-guide/commit/8cd0fdc819baf8178a16e3b3dcc77b3b90c11ec3))
22 | * **intersection-types:** update ([e5ffe1b](https://github.com/Rain120/typescript-guide/commit/e5ffe1bd61dd154329422a420c9a91f3346e6a90))
23 | * **keyof:** update usage ([37c61cb](https://github.com/Rain120/typescript-guide/commit/37c61cbf14eb66f5c84c8cd90a27b79183cc0bf7))
24 | * **utility types:** custom ([50e8703](https://github.com/Rain120/typescript-guide/commit/50e87037bc7ad9b20757efa1ad18734db428f0a5))
25 | * add Previously at keyword for descript the resource about it ([be81d8e](https://github.com/Rain120/typescript-guide/commit/be81d8e5f2f6d2892852f72143b09607ddc1d78a))
26 | * blog tips & pdfs & books ([310765f](https://github.com/Rain120/typescript-guide/commit/310765ffd4e95bcde3dc3a33c3ca7115f80d30f1))
27 | * compile-config about module resolver & flie inclusive; keyword about is ([4b5832d](https://github.com/Rain120/typescript-guide/commit/4b5832df75a82cd75b553463d1ed476f22d20fd1))
28 | * faqs about tsconfig module target ([d40988c](https://github.com/Rain120/typescript-guide/commit/d40988c26b6c287dc72aac94a4c76b2f07cfa8cf))
29 | * faqs add interface vs type ([3bf6171](https://github.com/Rain120/typescript-guide/commit/3bf61710c8395d8ba73adfc0ae4eb7a3be0f5021))
30 | * finished declaration ([b30964d](https://github.com/Rain120/typescript-guide/commit/b30964d056cd2c03bcaa0dd3a19a60215510ec90))
31 | * tsconfig - references ([ad24a19](https://github.com/Rain120/typescript-guide/commit/ad24a197efd8703ab818458246d141b3adf5f226))
32 | * tsconfig about file inclision keywords ([c566316](https://github.com/Rain120/typescript-guide/commit/c566316727123cb0998c1f09f6736c2902d1d1c6))
33 | * tsconfig module target; remove faqs module, target ([48d3e0f](https://github.com/Rain120/typescript-guide/commit/48d3e0f16f0957b08da24352ca73eb1e5770d382))
34 |
35 |
36 |
37 | ## [0.0.1](https://github.com/Rain120/typescript-guide/compare/77f36499665edfad4f0333d6a55f54a541177f06...0.0.1) (2020-12-30)
38 |
39 |
40 | ### Bug Fixes
41 |
42 | * add deploy folder, remove useless file with deploy.yml ([ae47a15](https://github.com/Rain120/typescript-guide/commit/ae47a15f31d84c749adeac9f4dcb8bd793860223))
43 | * changelog before commit ([904d7cd](https://github.com/Rain120/typescript-guide/commit/904d7cd67335a1455aade81ae5638d0d85c16016))
44 | * deploy workflows error ([eb9efce](https://github.com/Rain120/typescript-guide/commit/eb9efcee47d42d8cfd3eae039dc904c71e73fdf1))
45 | * deploy workflows error ([048dbe1](https://github.com/Rain120/typescript-guide/commit/048dbe1c70e0f0ecb914d8f44a14629938fac157))
46 | * deploy workflows error ([6aa3dae](https://github.com/Rain120/typescript-guide/commit/6aa3dae982f03588a9b9f69b9f31dcdb67b0d14c))
47 | * deploy workflows error ([eeb7ab2](https://github.com/Rain120/typescript-guide/commit/eeb7ab2d0d7487b5a43249d0f0181083178961dd))
48 | * index.styl ([15af71e](https://github.com/Rain120/typescript-guide/commit/15af71e4e0cab90a610166fae201e60cfdf88daa))
49 | * Invalid workflow filed with deploy yml ([6c0d64a](https://github.com/Rain120/typescript-guide/commit/6c0d64a7dacbb38c8b34adcc4d74fbd56bb1e99c))
50 | * monaco editor build bug (cannot require async component) ([906f6e8](https://github.com/Rain120/typescript-guide/commit/906f6e8379efe762d76f16381b657e4752be4dd4))
51 | * monaco editor show normal modal and can edit ([da7a4c9](https://github.com/Rain120/typescript-guide/commit/da7a4c9316b6bf245ceccea93f3518ddaf810f80))
52 | * nested sub-level directories path ([c6830ac](https://github.com/Rain120/typescript-guide/commit/c6830ac37ada02270874d8d3d7ab00fade02e51d))
53 | * README OKR path not found ([5d9739d](https://github.com/Rain120/typescript-guide/commit/5d9739d17602787fb8d1ad190d225fc572003920))
54 | * remove pre-commit changelog ([a8da639](https://github.com/Rain120/typescript-guide/commit/a8da6392c5c11ccb7148803cebe96a2068e873f5))
55 | * remove pre-commit deploy ([1d5830a](https://github.com/Rain120/typescript-guide/commit/1d5830ae9c4a2e6a6b83a573f9aa51e881b77ca7))
56 | * resolve advanced types path error ([8458a2c](https://github.com/Rain120/typescript-guide/commit/8458a2c6e2a22c53f387d2b53ba20f2c49e59d70))
57 | * the math logic description about intersection and union which at advanced types ([9bcc637](https://github.com/Rain120/typescript-guide/commit/9bcc637024767a71b0021c9a1f006fd3392e7ece))
58 | * update google analysis id ([2e1721b](https://github.com/Rain120/typescript-guide/commit/2e1721b7f5a7b671398f5d6ec2c094194c4229c0))
59 | * use commands install replace ci, because not package-lock.json ([64cfc90](https://github.com/Rain120/typescript-guide/commit/64cfc9003cb860bbdcb1855c971da4f1df1acc51))
60 | * utility types Record example error ([51ab092](https://github.com/Rain120/typescript-guide/commit/51ab092a23c030379f42f35920c0211d5f3b4cf2))
61 |
62 |
63 | ### Features
64 |
65 | * add test & editor at template and docs ([19faa8a](https://github.com/Rain120/typescript-guide/commit/19faa8a69ce121ba3adeaaaa4eefbdba64bf0381))
66 | * add tips, faqs folder; how to write docs md ([ff42474](https://github.com/Rain120/typescript-guide/commit/ff42474843622fcd2f6bb4ad13ea075934c039bc))
67 | * advanced types nullable; update union, assertion; others chores ([1b5936a](https://github.com/Rain120/typescript-guide/commit/1b5936aac1fe2c6363c90083231f66779b654a1e))
68 | * build in objects ([b62cd07](https://github.com/Rain120/typescript-guide/commit/b62cd07384f6423400d485bc3c4b68c6649c0ec2))
69 | * class ([78ff3cc](https://github.com/Rain120/typescript-guide/commit/78ff3ccf5e321f198777deb8fd20dc487add0bc0))
70 | * decorators usage ([36be18e](https://github.com/Rain120/typescript-guide/commit/36be18ee8e9f0914b8470e1e12dd9b9474c2f8e0))
71 | * decorators; plugin with math latex ([4364958](https://github.com/Rain120/typescript-guide/commit/4364958b84092d08a312ea839e730de008d1847e))
72 | * function ([5dba78c](https://github.com/Rain120/typescript-guide/commit/5dba78cd2eb6d18c70c4524ae328f4514c5eb1dd))
73 | * github action deploy workflows ([a98f275](https://github.com/Rain120/typescript-guide/commit/a98f27562f0cf7e3a82b46fa95fba8c1f2cd678b))
74 | * github action deploy workflows ([ae5128e](https://github.com/Rain120/typescript-guide/commit/ae5128e2dd7521698a0b5f11f783f48d41022e12))
75 | * infer ([ddb4ae9](https://github.com/Rain120/typescript-guide/commit/ddb4ae96a8e669e266f7d76533e6f6c5660d3286))
76 | * init typscript guide & add guide, introduction, base ([365b637](https://github.com/Rain120/typescript-guide/commit/365b637d872cc92c23a04c09788d50001ee46a73))
77 | * intersection & union types; utility version; typescripts reference ([06fc3de](https://github.com/Rain120/typescript-guide/commit/06fc3de9cd11890024e172ee69b480924ddad295))
78 | * keyword with extends, implements ([a784b4e](https://github.com/Rain120/typescript-guide/commit/a784b4e23fd30c6a8cb754244e4fa1a2df6fb9ad))
79 | * keyword: is, keyof, in, typeof, instanceof; type guard; add vuepress plugin ([81f3b55](https://github.com/Rain120/typescript-guide/commit/81f3b5537f5aca20a4b10219d6cb216df2d51fea))
80 | * plop auto create docs model ([1f5a2f9](https://github.com/Rain120/typescript-guide/commit/1f5a2f94bbd7a430bbfbb48a09718b8ec9d14190))
81 | * plop new docs & update alias; update plop template; add docs catalog & folders ([dd5326a](https://github.com/Rain120/typescript-guide/commit/dd5326ac2934069c2cb10238c674e4dc86844274))
82 | * refactor types(intersection, union, guard) to advanced types ([bde41ab](https://github.com/Rain120/typescript-guide/commit/bde41ab8e61ae59f21c907c7a1a86e932ee71f31))
83 | * ts basic type; update logo; guide; add editorconfig ([c0b6eb2](https://github.com/Rain120/typescript-guide/commit/c0b6eb272ab4d87706902cdda365230e507b860b))
84 | * ts operator; compile config; fix: playground frame width bug ([f2bcaa0](https://github.com/Rain120/typescript-guide/commit/f2bcaa05bfdf574037ec54ed3e651ce1d1353b5c))
85 | * ts operators ([4e009df](https://github.com/Rain120/typescript-guide/commit/4e009dfa98c42be63705d71130af1bfc46861d19))
86 | * type assertion ([f77f51c](https://github.com/Rain120/typescript-guide/commit/f77f51c574f036d6079742eca8f8affa7b06f617))
87 | * typescript blog ([13e29c4](https://github.com/Rain120/typescript-guide/commit/13e29c418ed7e351e134e55519f31022785f5681))
88 | * **heading:** 加入特殊 heading 的处理; ignore IDE 相关的文件 ([5e9070b](https://github.com/Rain120/typescript-guide/commit/5e9070baf3b36cc0e753b9bde3a8aaec58590314))
89 | * update the okrs about guide ([a762e9c](https://github.com/Rain120/typescript-guide/commit/a762e9cb156ac0bcdbdc64f0b477e41c49fb9e8d))
90 | * utility types; alias set bottom title; update generics params; ([a306a25](https://github.com/Rain120/typescript-guide/commit/a306a25c512246ef230a445ccb4e292eef8b8a7d))
91 | * vuepress docs template ([77f3649](https://github.com/Rain120/typescript-guide/commit/77f36499665edfad4f0333d6a55f54a541177f06))
92 | * wip generics, interface; add okr about the doc ([d2f6397](https://github.com/Rain120/typescript-guide/commit/d2f6397641ec4a590a51f297c1a9d61564500dff))
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Rain120
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 | [](https://github.com/Rain120/typescript-guide/watchers)
9 | [](https://github.com/Rain120/typescript-guide/stargazers) [](https://github.com/Rain120/typescript-guide/network/members)
10 |
11 | [](https://github.com/Rain120/typescript-guide/issues) [](https://github.com/Rain120/typescript-guide/pulls) [](https://github.com/Rain120/typescript-guide/commits/master)
12 |
13 | 
14 | [](https://github.com/Rain120/typescript-guide/blob/master/package.json) [](https://github.com/Rain120/typescript-guide/blob/master/LICENSE)
15 |
16 |
17 |
18 | ## 😚 Welcome
19 |
20 | Welcome to the Typescript Guide.
21 |
22 | ## 🎮 TL;DR
23 |
24 |
25 | [Document](https://rain120.github.io/typescript-guide/)
26 |
27 | ## ✍ Why am I doing this?
28 |
29 | Write documents for how to easily use typescript.
30 | ## 🍾 Objective Key Result (OKR)
31 |
32 | ### Objective
33 |
34 | Learning all about the base of Typescript, and practice it
35 |
36 | ### Key Result
37 |
38 | - [x] [Compile Config](./docs/zh/compile-config/README.md)
39 |
40 | - [x] [Basic](./docs/zh/basic/README.md)
41 |
42 | - [x] [Type Assertion](./docs/zh/advanced-types/type-assertion/README.md)
43 |
44 | - [x] [Advanced Types](./docs/zh/advanced-types/README.md)
45 |
46 | - [x] [Intersection Types](./docs/zh/advanced-types/intersection-types/README.md)
47 |
48 | - [x] [Union Types](./docs/zh/advanced-types/union-types/README.md)
49 |
50 | - [x] [Type Guard](./docs/zh/advanced-types/type-guard/README.md)
51 |
52 | - [x] [Nullable](./docs/zh/advanced-types/nullable/README.md)
53 |
54 | - [x] [Array](./docs/zh/array/README.md)
55 |
56 | - [x] [Function](./docs/zh/function/README.md)
57 |
58 | - [ ] [Decorators](./docs/zh/decorators/README.md)
59 |
60 | - [ ] [Class](./docs/zh/class/README.md)
61 |
62 | - [x] [内置对象](./docs/zh/built-in-objects/README.md)
63 |
64 | - [ ] [Interface](./docs/zh/interface/README.md)
65 |
66 | - [ ] [Generics](./docs/zh/generics/README.md)
67 |
68 | - [x] [Operator](./docs/zh/operator/README.md)
69 |
70 | - [x] [Keyword](./docs/zh/keyword/README.md)
71 |
72 | - [x] [is](./docs/zh/is/README.md)
73 |
74 | - [x] [keyof](./docs/zh/keyof/README.md)
75 |
76 | - [x] [in](./docs/zh/in/README.md)
77 |
78 | - [x] [typeof](./docs/zh/typeof/README.md)
79 |
80 | - [x] [instanceof](./docs/zh/instanceof/README.md)
81 |
82 | - [x] [extends](./docs/zh/extends/README.md)
83 |
84 | - [x] [implements](./docs/zh/implements/README.md)
85 |
86 | - [ ] [infer](./docs/zh/implements/README.md)
87 |
88 | - [x] [Utility Types](./docs/zh/utility-types/README.md)
89 |
90 | - [ ] [Tips](./docs/zh/tips/README.md)
91 |
92 | - [ ] [FAQs](./docs/zh/faqs/README.md)
93 |
94 |
95 |
98 |
99 | ## 🤝 Contributing
100 |
101 | 
102 |
103 | We welcome all contributions. You can submit any ideas as [pull requests](https://github.com/Rain120/typescript-guide/pulls) or as a GitHub [issue](https://github.com/Rain120/typescript-guide/issues).
104 |
105 | [How to write Docs](how-to-write-docs.md)
106 |
107 | ## 🔗 Links
108 |
109 |
110 |
111 | [Online Docs](https://rain120.github.io/typescript-guide/)
112 |
113 | ## 👨🏭 Author
114 |
115 | > Front-End development engineer, technology stack: React + Typescript + Mobx, also used Vue + Vuex for a while
116 |
117 | - [Github](https://github.com/Rain120)
118 | - [知乎](https://www.zhihu.com/people/yan-yang-nian-hua-120/activities)
119 | - [掘金](https://juejin.im/user/57c616496be3ff00584f54db)
120 |
121 | ## 📝 License
122 |
123 | [MIT](https://github.com/Rain120/typescript-guide/blob/master/LICENSE)
124 |
125 | Copyright © 2020-present [Rain120](https://github.com/Rain120).
126 |
127 | ## ☕ Coffee or Tea
128 |
129 | 
130 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ["@commitlint/config-conventional"],
3 | rules: {
4 | "type-enum": [
5 | 2,
6 | "always",
7 | [
8 | "feat",
9 | "fix",
10 | "docs",
11 | "style",
12 | "refactor",
13 | "perf",
14 | "test",
15 | "build",
16 | "ci",
17 | "chore",
18 | "revert",
19 | "config",
20 | "wip"
21 | ]
22 | ],
23 | "subject-full-stop": [0, "never"],
24 | "subject-case": [0, "never"],
25 | "header-max-length": [0, "always", 150]
26 | }
27 | };
28 |
--------------------------------------------------------------------------------
/docs/.vuepress/components/Answer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{title}}
4 |
5 |
6 |
7 |
32 |
33 |
35 |
--------------------------------------------------------------------------------
/docs/.vuepress/components/Editor.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
129 |
130 |
--------------------------------------------------------------------------------
/docs/.vuepress/components/MySWUpdatePopup.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
19 |
20 |
83 |
--------------------------------------------------------------------------------
/docs/.vuepress/config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin')
3 | const plugins = require('./utils/plugins');
4 | const { sidebarHelper, sortSidebar } = require('./utils/sidebarHelper');
5 | const nav = require('./utils/nav');
6 | const slugify = require('@vuepress/shared-utils').slugify
7 |
8 | const sidebar = sortSidebar(sidebarHelper());
9 | // console.log(sidebar)
10 |
11 | const fs = require('fs')
12 |
13 | const SPECIAL_HEADINGS = {
14 | '!': 'exclamation',
15 | '?': 'question',
16 | '+ -': 'plus-and-minus',
17 | };
18 |
19 | module.exports = {
20 | // 替换成你的仓库名
21 | base: '/typescript-guide/',
22 | title: 'Typescript 指导书',
23 | description: 'Welcome to Typescript Guide',
24 | port: 9527,
25 | // dest: 'dist',
26 | // head 配置
27 | head: [
28 | ['link', { rel: 'icon', href: '/ts-logo.png' }],
29 | ['link', { rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/katex.min.css' }],
30 | ['link', { rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/2.10.0/github-markdown.min.css' }],
31 | ['link', { rel: 'manifest', href: '/manifest.json' }],
32 | ['meta', { name: 'theme-color', content: '#3eaf7c' }],
33 | ['meta', { name: 'apple-mobile-web-app-capable', content: 'yes' }],
34 | ['meta', { name: 'apple-mobile-web-app-status-bar-style', content: 'black' }],
35 | ['link', { rel: 'apple-touch-icon', href: '/icons/apple-touch-icon-152x152.png' }],
36 | ['link', { rel: 'mask-icon', href: '/icons/safari-pinned-tab.svg', color: '#3eaf7c' }],
37 | ['meta', { name: 'msapplication-TileImage', content: '/icons/msapplication-icon-144x144.png' }],
38 | ['meta', { name: 'msapplication-TileColor', content: '#000000' }],
39 | ],
40 | // 别名配置
41 | configureWebpack: {
42 | resolve: {
43 | alias: {
44 | '@images': path.join(__dirname, '../..'),
45 | }
46 | }
47 | },
48 | chainWebpack:(config, isServer) => {
49 | // config.resolve.alias.set('@images',path.resolve(__dirname, '../../'))
50 | config.plugin('monaco-editor').use(MonacoWebpackPlugin, [
51 | {
52 | // Languages are loaded on demand at runtime
53 | languages: [
54 | 'javascript',
55 | 'typescript',
56 | ]
57 | }
58 | ])
59 | },
60 | locales: {
61 | '/': {
62 | lang: 'zh-CN',
63 | }
64 | },
65 | // markdown
66 | markdown: {
67 | lineNumbers: true,
68 | /**
69 | * 解决一个 "无实质内容的标题导致 permalink 出错" 的问题,
70 | * 目前发现有若干个有点问题的, 如 `!`
71 | *
72 | * @todo: 如果开始有多类似的个例, 可以引入特殊的 "heading anchor" 格式, 并统一处理
73 | *
74 | * 参考 : http://caibaojian.com/vuepress/config/#markdown-slugify
75 | *
76 | * @param {string} heading
77 | * @return {string|*|string}
78 | */
79 | slugify: (heading) => {
80 | const originResult = slugify(heading)
81 |
82 | const trimmedHeading = (heading || '').trim()
83 | if (trimmedHeading in SPECIAL_HEADINGS) {
84 | return SPECIAL_HEADINGS[(heading || '').trim()] || ''
85 | }
86 | return originResult
87 | },
88 | anchor: {
89 | permalink: true,
90 | },
91 | toc: {
92 | includeLevel: [1, 2],
93 | },
94 | extendMarkdown: md => {
95 | md.set({ html: true });
96 | md.use(require('markdown-it-katex'));
97 | md.use(require('markdown-it-task-lists'));
98 | md.use(require('markdown-it-imsize'), { autofill: true });
99 | }
100 | },
101 | // 主题配置
102 | themeConfig: {
103 | theme: 'vue',
104 | repo: 'https://github.com/Rain120/typescript-guide',
105 |
106 | sidebar,
107 | nav,
108 |
109 | // polyfill IE
110 | evergreen: true,
111 |
112 | // search
113 | search: true,
114 | searchMaxSuggestions: 10,
115 | // 申请
116 | // https://docsearch.algolia.com/apply/
117 | // algolia: {
118 | // apiKey: '',
119 | // indexName: ''
120 | // },
121 |
122 | // PWA
123 | serviceWorker: true,
124 |
125 | displayAllHeaders: true,
126 |
127 | smoothScroll: true,
128 |
129 | // footer
130 | date_format: 'yyyy-MM-dd',
131 | lastUpdated: 'Last Updated',
132 | repoLabel: '查看源码',
133 | docsDir: 'docs',
134 | docsBranch: 'master',
135 | editLinks: true,
136 | editLinkText: '帮助我们改善此页面!'
137 | },
138 | plugins
139 | };
140 |
--------------------------------------------------------------------------------
/docs/.vuepress/enhanceApp.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: Rainy
3 | * @Date: 2020-02-27 16:38:27
4 | * @LastEditors: Rainy
5 | * @LastEditTime: 2021-03-12 16:16:16
6 | */
7 |
8 | // import copy from './utils/copy';
9 |
10 | export default ({ Vue, options, router, siteData, isServer }) => {
11 | if (typeof process === 'undefined' || process.env.VUE_ENV !== 'server') {
12 | router.onReady(() => {
13 | const { app } = router;
14 |
15 | app.$once('hook:mounted', () => {
16 | setTimeout(() => {
17 | const { hash } = document.location;
18 | if (hash.length > 1) {
19 | const id = decodeURIComponent(hash.substring(1));
20 | const element = document.getElementById(id);
21 | element && element.scrollIntoView();
22 | }
23 | }, 500);
24 | });
25 | });
26 | }
27 |
28 | setTimeout(() => {
29 | try {
30 | //对document的判断是防止编译的时候报错
31 | document &&
32 | (() => {
33 | // copy();
34 | })();
35 | } catch (e) {
36 | console.error(e.message);
37 | }
38 | }, 500);
39 | };
40 |
--------------------------------------------------------------------------------
/docs/.vuepress/public/images/docs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rain120/typescript-guide/90432f8d4e8b7b20a76d678886f7e1075c3ae6ff/docs/.vuepress/public/images/docs.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/images/icons/icon-128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rain120/typescript-guide/90432f8d4e8b7b20a76d678886f7e1075c3ae6ff/docs/.vuepress/public/images/icons/icon-128x128.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/images/icons/icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rain120/typescript-guide/90432f8d4e8b7b20a76d678886f7e1075c3ae6ff/docs/.vuepress/public/images/icons/icon-144x144.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/images/icons/icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rain120/typescript-guide/90432f8d4e8b7b20a76d678886f7e1075c3ae6ff/docs/.vuepress/public/images/icons/icon-152x152.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/images/icons/icon-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rain120/typescript-guide/90432f8d4e8b7b20a76d678886f7e1075c3ae6ff/docs/.vuepress/public/images/icons/icon-192x192.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/images/icons/icon-384x384.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rain120/typescript-guide/90432f8d4e8b7b20a76d678886f7e1075c3ae6ff/docs/.vuepress/public/images/icons/icon-384x384.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/images/icons/icon-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rain120/typescript-guide/90432f8d4e8b7b20a76d678886f7e1075c3ae6ff/docs/.vuepress/public/images/icons/icon-512x512.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/images/icons/icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rain120/typescript-guide/90432f8d4e8b7b20a76d678886f7e1075c3ae6ff/docs/.vuepress/public/images/icons/icon-72x72.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/images/icons/icon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rain120/typescript-guide/90432f8d4e8b7b20a76d678886f7e1075c3ae6ff/docs/.vuepress/public/images/icons/icon-96x96.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rain120/typescript-guide/90432f8d4e8b7b20a76d678886f7e1075c3ae6ff/docs/.vuepress/public/logo.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Vuepress Doc Template",
3 | "short_name": "Vuepress Doc Template",
4 | "theme_color": "#3EAF7C",
5 | "background_color": "#3EAF7C",
6 | "display": "standalone",
7 | "Scope": "/",
8 | "start_url": "/",
9 | "icons": [
10 | {
11 | "src": "images/icons/icon-72x72.png",
12 | "sizes": "72x72",
13 | "type": "image/png"
14 | },
15 | {
16 | "src": "images/icons/icon-96x96.png",
17 | "sizes": "96x96",
18 | "type": "image/png"
19 | },
20 | {
21 | "src": "images/icons/icon-128x128.png",
22 | "sizes": "128x128",
23 | "type": "image/png"
24 | },
25 | {
26 | "src": "images/icons/icon-144x144.png",
27 | "sizes": "144x144",
28 | "type": "image/png"
29 | },
30 | {
31 | "src": "images/icons/icon-152x152.png",
32 | "sizes": "152x152",
33 | "type": "image/png"
34 | },
35 | {
36 | "src": "images/icons/icon-192x192.png",
37 | "sizes": "192x192",
38 | "type": "image/png"
39 | },
40 | {
41 | "src": "images/icons/icon-384x384.png",
42 | "sizes": "384x384",
43 | "type": "image/png"
44 | },
45 | {
46 | "src": "images/icons/icon-512x512.png",
47 | "sizes": "512x512",
48 | "type": "image/png"
49 | }
50 | ],
51 | "splash_pages": null
52 | }
--------------------------------------------------------------------------------
/docs/.vuepress/public/ts-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rain120/typescript-guide/90432f8d4e8b7b20a76d678886f7e1075c3ae6ff/docs/.vuepress/public/ts-logo.png
--------------------------------------------------------------------------------
/docs/.vuepress/styles/index.styl:
--------------------------------------------------------------------------------
1 | #app {
2 | .page {
3 | #gitalk-container {
4 | margin: auto;
5 | width: 60%;
6 | }
7 | .theme-default-content:not(.custom) {
8 | max-width: 840px;
9 | }
10 | }
11 |
12 | .page-nav, .page-edit {
13 | max-width: 840px;
14 | }
15 |
16 | details {
17 | border-radius: 4px;
18 | padding: .5em .5em;
19 | &:focus {
20 | outline: none;
21 | }
22 | }
23 |
24 | summary {
25 | font-weight: bold;
26 | margin: -.5em -.5em;
27 | margin-bottom: .8em;
28 | &:focus {
29 | outline: none;
30 | }
31 | }
32 |
33 | code {
34 | background: none;
35 | }
36 |
37 | .theorem {
38 | margin: 1rem 0;
39 | padding: .1rem 1.5rem;
40 | border-radius: 0.4rem;
41 | background-color: #f0f4f8;
42 | .title {
43 | font-weight: bold;
44 | }
45 | }
46 |
47 | .custom-block {
48 | &.right {
49 | color: transparentify($textColor, 0.4);
50 | font-size: 0.9rem;
51 | text-align: right;
52 | }
53 | }
54 | }
55 |
56 | ::-webkit-scrollbar {
57 | width: 8px;
58 | height: 8px;
59 | border-radius: 10px;
60 | background-color: #F5F5F5;
61 | }
62 |
63 | ::-webkit-scrollbar-track {
64 | border-radius: 10px;
65 | -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
66 | background-color: #F5F5F5;
67 | }
68 |
69 | ::-webkit-scrollbar-thumb {
70 | border-radius: 10px;
71 | -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
72 | border-radius: 10px;
73 | background-image: -webkit-gradient(
74 | linear,
75 | left bottom, left top,
76 | color-stop(.44, rgb(60, 186, 146)),
77 | color-stop(.72, rgb(253, 187, 45)),
78 | color-stop(.86, rgb(253, 187, 45))
79 | );
80 | transition: .3s ease-in-out;
81 | }
82 |
83 | ::-webkit-scrollbar-thumb:hover {
84 | background-image: -webkit-gradient(
85 | linear,
86 | left bottom, left top,
87 | color-stop(.44, rgb(253, 187, 45)),
88 | olor-stop(.72, rgb(253, 187, 45)),
89 | color-stop(.86, rgb(60, 186, 146))
90 | );
91 | transition: .3s ease-in-out;
92 | }
93 |
--------------------------------------------------------------------------------
/docs/.vuepress/utils/alias.json:
--------------------------------------------------------------------------------
1 | {
2 | "guide": "介绍",
3 | "what-is-typescript": "Typescript 是什么? ",
4 | "compile-config": "Typescript 编译配置",
5 | "declaration": "Typescript 声明文件",
6 | "basic": "Typescript 基础类型",
7 | "advanced-types": "Typescript 高级类型",
8 | "type-assertion": "Typescript 类型断言",
9 | "intersection-types": "TypeScript 交叉类型",
10 | "union-types": "Typescript 联合类型",
11 | "type-guard": "Typescript 类型保护",
12 | "nullable": "Typescript Nullable",
13 | "array": "Typescript 数组",
14 | "function": "TypeScript 函数",
15 | "class": "Typescript 类",
16 | "built-in-objects": "Typescript 内置对象",
17 | "decorators": "Typescript 装饰器",
18 | "interface": "Typescript 接口",
19 | "generics": "Typescript 泛型",
20 | "keyword": "Typescript 关键字",
21 | "is": "is",
22 | "keyof": "keyof",
23 | "in": "in",
24 | "typeof": "typeof",
25 | "instanceof": "instanceof",
26 | "operator": "Typescript 运算符",
27 | "utility-types": "Typescript 使用工具类型",
28 | "extends": "extends",
29 | "implements": "implements",
30 | "infer": "infer",
31 | "blog": "博客",
32 | "file-inclusion": "Typescript 文件包含相关配置",
33 | "references": "tsconfig - references",
34 | "tsconfig-module-target": "Typescript Module Target",
35 | "interface-vs-type": "interface 和 type 有什么异同点?",
36 | "module-resolver": "Typescript 模块解析",
37 | "custom-utility-types": "自定义工具类型",
38 | "if-else": "条件类型",
39 | "spread": "拓展运算符",
40 | "tips": "Typescript Tips",
41 | "faqs": "Typescript FAQs"
42 | }
--------------------------------------------------------------------------------
/docs/.vuepress/utils/copy.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: Rainy
3 | * @Date: 2020-02-27 16:38:27
4 | * @LastEditors: Rainy
5 | * @LastEditTime: 2020-08-02 16:07:40
6 | */
7 |
8 | export default (userName = 'Rain120') => {
9 | function addCopy(e) {
10 | let copyTxt = '';
11 | e.preventDefault(); // 取消默认的复制事件
12 | copyTxt = window.getSelection(0).toString();
13 | copyTxt = `${copyTxt}\n作者: ${userName}\n原文: ${window.location.href}\n著作权归作者所有。商业转载请联系作者获得授权, 非商业转载请注明出处。`;
14 | const clipboardData = e.clipboardData || window.clipboardData;
15 | clipboardData.setData('text', copyTxt);
16 | }
17 | document.addEventListener('cut', e => {
18 | addCopy(e);
19 | });
20 | document.addEventListener('copy', e => {
21 | addCopy(e);
22 | });
23 | };
24 |
--------------------------------------------------------------------------------
/docs/.vuepress/utils/nav.js:
--------------------------------------------------------------------------------
1 | module.exports = [
2 | {
3 | text: 'Study Notes',
4 | link: 'https://rain120.github.io/study-notes/',
5 | target: '_blank'
6 | },
7 | // {
8 | // text: 'Languages',
9 | // ariaLabel: 'Language Menu',
10 | // items: [
11 | // { text: 'Chinese', link: '/zh/guide/' },
12 | // { text: 'English', link: '/en/guide/' }
13 | // ]
14 | // },
15 | {
16 | text: 'Hot Repo',
17 | items: [
18 | {
19 | text: 'awesome-javascript-code-implementation',
20 | link: 'https://awesome-javascript-code-implementation.netlify.com/',
21 | target: '_blank'
22 | },
23 | {
24 | text: 'qq-music-api',
25 | link: 'https://rain120.github.io/qq-music-api/',
26 | target: '_blank'
27 | },
28 | {
29 | text: 'more',
30 | link: 'https://github.com/rain120',
31 | target: '_blank'
32 | },
33 | ]
34 | },
35 | {
36 | text: 'Github',
37 | link: 'https://github.com/rain120',
38 | target: '_blank'
39 | }
40 | ];
41 |
--------------------------------------------------------------------------------
/docs/.vuepress/utils/plugins.js:
--------------------------------------------------------------------------------
1 | const moment = require('moment');
2 |
3 | const containers = [
4 | // 你可以多次使用这个插件
5 | [
6 | 'vuepress-plugin-container',
7 | {
8 | type: 'right',
9 | defaultTitle: '',
10 | },
11 | ],
12 | [
13 | 'vuepress-plugin-container',
14 | {
15 | type: 'theorem',
16 | before: info => `',
18 | },
19 | ],
20 | // 这是 VuePress 默认主题使用这个插件的方式
21 | [
22 | 'vuepress-plugin-container',
23 | {
24 | type: 'tip',
25 | defaultTitle: {
26 | '/': 'TIP',
27 | '/zh/': '提示',
28 | },
29 | },
30 | ],
31 | ]
32 |
33 | module.exports = [
34 | ['@vuepress/back-to-top'],
35 | [
36 | '@vuepress/google-analytics',
37 | {
38 | ga: 'UA-172045751-1'
39 | }
40 | ],
41 | [
42 | '@vuepress/medium-zoom',
43 | {
44 | // selector: 'img.zoom-custom-imgs',
45 | options: {
46 | margin: 16
47 | }
48 | }
49 | ],
50 | [
51 | 'vuepress-plugin-awesome-gitalk',
52 | {
53 | home: false,
54 | ignorePaths: ['/zh/guide/'],
55 | gitalk: {
56 | clientID: '13f222b6ec6782dbe85f',
57 | clientSecret: '60984ee0c8926c160d2dc1a32e2769f2002e0a1b',
58 | repo: 'typescript-guide',
59 | owner: 'Rain120',
60 | admin: ['Rain120'],
61 | distractionFreeMode: true,
62 | language: 'zh-CN',
63 | }
64 | }
65 | ],
66 | ['@vuepress/pwa',
67 | {
68 | serviceWorker: true,
69 | popupComponent: 'MySWUpdatePopup',
70 | updatePopup: {
71 | '/': {
72 | message: "官人, 人家又有新货了, 快来玩呀",
73 | buttonText: "我来啦"
74 | },
75 | '/zh/': {
76 | message: "官人, 人家又有新货了, 快来玩呀",
77 | buttonText: "我来啦"
78 | }
79 | }
80 | }
81 | ],
82 | ['@vuepress/blog'],
83 | [
84 | '@vuepress/last-updated',
85 | {
86 | transformer: (timestamp, lang) => {
87 | moment.locale(lang)
88 | return moment(timestamp).fromNow()
89 | }
90 | }
91 | ],
92 | [
93 | 'vuepress-plugin-mathjax',
94 | {
95 | target: 'svg',
96 | macros: {
97 | '*': '\\times',
98 | },
99 | },
100 | ],
101 | ...containers,
102 | ];
103 |
--------------------------------------------------------------------------------
/docs/.vuepress/utils/sidebarHelper.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: Rainy
3 | * @Date: 2020-02-27 16:38:27
4 | * @LastEditors: Rainy
5 | * @LastEditTime: 2020-07-11 17:44:01
6 | */
7 |
8 | const fs = require('fs');
9 | const path = require('path');
10 |
11 | const language = 'zh';
12 | const filePath = path.join(__dirname, `../../${language}`);
13 | const ignore = ['images', '.vuepress', '.DS_Store'];
14 | const README_REG = /README/;
15 |
16 | // INFO: 从 package.json 获取你的文档名字, 主要为了配置多层级子目录
17 | const docsPath = process.cwd();
18 | const pkg = require(`${docsPath}/package.json`);
19 | const pkgName = pkg.name || docsPath.trim().split('/').slice(-1).toString();
20 |
21 | /**
22 | * @description 特殊处理文档顺序
23 | * alias 的顺序决定了文档菜单的目录顺序, 子菜单亦可
24 | * Eg:
25 | * p2: p2
26 | * p1: p1
27 | * p1-c2: p1-c2
28 | * p1-c1: p1-c1
29 | * -> 菜单顺序是
30 | * p2
31 | * p1
32 | * c2
33 | * c1
34 | */
35 | const alias = require('./alias.json');
36 |
37 | const mapper = code => {
38 | return alias[code];
39 | }
40 |
41 | const isFile = ({ dir = filePath, fPath }) =>
42 | fs.statSync(path.join(dir, fPath)).isFile();
43 |
44 | function syncDirPath(file = filePath) {
45 | return fs.readdirSync(file) || [];
46 | }
47 |
48 | function helper({ dir, fPath }) {
49 | const prefixPath = dir.split(`${pkgName}/docs`)[1];
50 | const currentPath = path.join(dir, fPath);
51 |
52 | const children = syncDirPath(currentPath)
53 | .filter(fPath => !ignore.includes(fPath))
54 | .map((sub, index) => {
55 | const fsStats = fs.statSync(path.join(currentPath, sub));
56 |
57 | if (fsStats.isDirectory()) {
58 | return helper({ dir: currentPath, fPath: sub });
59 | } else if (fsStats.isFile() && !README_REG.test(sub)) {
60 | const name = sub.replace('\.md', '');
61 | return {
62 | title: mapper(name) || `${name}`,
63 | key: name,
64 | path: `${prefixPath}/${fPath}/${name}`,
65 | }
66 | }
67 | }).filter(Boolean);
68 |
69 | return {
70 | title: mapper(fPath) || `${fPath}`,
71 | key: fPath,
72 | path: `${prefixPath}/${fPath}/`,
73 | collapsable: true,
74 | children: Array.isArray(children) ? children : [children],
75 | }
76 | }
77 |
78 | function sidebarHelper(dir = filePath) {
79 | return syncDirPath(dir)
80 | .filter(fPath => !isFile({ fPath }) && !ignore.includes(fPath))
81 | .map((fPath, dirIndex) => {
82 | return helper({ dir, fPath }) || [];
83 | });
84 | }
85 |
86 | function findIndex(value) {
87 | return Object.keys(alias).findIndex(item => item === value)
88 | }
89 |
90 | function sortSidebar(sidebar) {
91 | sidebar.sort((a, b) => {
92 | return findIndex(a.key) - findIndex(b.key);
93 | });
94 | for (const item of sidebar) {
95 | if (item && Array.isArray(item.children)) {
96 | item.children = sortSidebar(item.children);
97 | }
98 | }
99 | return sidebar;
100 | }
101 |
102 | module.exports = {
103 | sidebarHelper,
104 | sortSidebar,
105 | };
106 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | home: true
3 | activity: true
4 | heroImage: /images/docs.png
5 | actionText: 快速上手 👉
6 | actionLink: /zh/guide/
7 |
8 | # tagline: Welcome to the Typescript Guide
9 |
10 | features:
11 |
12 | - title: 清晰性
13 | details: 通过文档清晰准确的讲解 Typescript 的知识点, 让你更加快速的了解Typescript
14 |
15 | - title: 开放性
16 | details: 完全开源, 并接受您的 PR 和 Issue
17 |
18 | footer: MIT Licensed | Copyright © 2020-present Rain120
19 | ---
20 |
--------------------------------------------------------------------------------
/docs/zh/advanced-types/README.md:
--------------------------------------------------------------------------------
1 | ## 目录
2 |
3 | :::theorem 高级类型
4 | Typescript 高级类型
5 | :::
6 |
7 | - [TypeScript 交叉类型](./intersection-types/README.md)
8 |
9 | - [Typescript 联合类型](./union-types/README.md)
10 |
11 | - [Typescript 类型保护](./type-guard/README.md)
12 |
13 | - [Typescript Nullable](./nullable/README.md)
14 |
15 | ## 参考资料
16 |
17 | [Handbook - advanced types](https://www.typescriptlang.org/docs/handbook/advanced-types.html)
18 |
--------------------------------------------------------------------------------
/docs/zh/advanced-types/intersection-types/README.md:
--------------------------------------------------------------------------------
1 | ## 定义
2 |
3 | :::theorem 交叉类型
4 | 交叉类型是将多个类型合并为一个类型。 这让我们可以把现有的多种类型叠加到一起成为一种类型, 它包含了所需的所有类型的特性。
5 | :::
6 |
7 | **Note:** 交叉类型是 **或** 的关系, 即 $A \cup B$, 使用 `&` 运算符。**如果两个类型中出现相同的key,但是类型不同**,**则该key为never**。
8 |
9 | ## 使用
10 |
11 | ```ts
12 | interface Boy {
13 | handsome: boolean;
14 | name?: string;
15 | }
16 |
17 | interface Girl {
18 | cute: boolean;
19 | name?: string;
20 | }
21 |
22 | // {
23 | // cute: boolean;
24 | // handsome: boolean;
25 | // name?: never;
26 | // }
27 | type Person = Boy & Girl;
28 |
29 | const someone: Person = {
30 | handsome: true,
31 | cute: false,
32 | name: 'Rain120'
33 | };
34 | ```
35 |
36 | 大多是在混入 `(mixins)` 或其它不适合典型面向对象模型的地方看到交叉类型的使用。如下示:
37 |
38 | ```ts
39 | function extend(first: T, second: U): T & U {
40 | let result = {};
41 | for (let id in first) {
42 | (result)[id] = (first)[id];
43 | }
44 | for (let id in second) {
45 | if (!result.hasOwnProperty(id)) {
46 | (result)[id] = (second)[id];
47 | }
48 | }
49 | return result;
50 | }
51 |
52 | class Person {
53 | constructor(public name: string) {}
54 | }
55 | interface Loggable {
56 | log(): void;
57 | }
58 | class ConsoleLogger implements Loggable {
59 | log() {
60 | // ...
61 | }
62 | }
63 | var jim = extend(new Person('Jim'), new ConsoleLogger());
64 | var n = jim.name;
65 | jim.log();
66 | ```
67 |
68 | ## 实现
69 |
70 | ```ts
71 | interface IntersectionTypes {
72 | assign(target: T, source: U): T & U;
73 | }
74 | ```
75 |
76 | ## 快来耍耍啊
77 |
78 | ### 🌰🌰
79 |
80 |
81 |
82 | ```
83 | // template
84 | ```
85 |
86 | ### 游乐场
87 |
88 |
89 |
90 |
93 |
94 | ### 参考答案
95 |
96 | ```ts
97 | // answer
98 | ```
99 |
100 | ## 参考资料
101 |
102 | [handbook - intersection-types](https://www.typescriptlang.org/docs/handbook/advanced-types.html#intersection-types)
103 |
104 | [数学公式参考](https://latexlive.com/)
105 |
--------------------------------------------------------------------------------
/docs/zh/advanced-types/nullable/README.md:
--------------------------------------------------------------------------------
1 | ## 定义
2 |
3 | :::theorem Nullable
4 | `TypeScript` 里空类型 `(void)` 有两种: `undefined` 与 `null`, 是 `(除never外)` 其它所有类型的子类型。
5 |
6 | 默认情况下, 类型检查器认为 `null`与 `undefined`可以赋值给任何类型。 `null`与 `undefined`是所有其它类型的一个有效值。
7 | :::
8 |
9 | 解决方式有两种:
10 |
11 | ### 可选参数和可选属性
12 |
13 | 当你使用了 `--strictNullChecks` 配置, 可选参数列表会自动加上 `| nudefined`。
14 |
15 | ```ts
16 | function setName(name?: string) {
17 | return name || 'Rain120';
18 | }
19 |
20 | setName('Lily');
21 | setName();
22 |
23 | ```
24 |
25 | ### 类型保护 和 类型断言
26 |
27 | #### [类型保护](../type-guard/README.md)
28 |
29 | ```ts
30 | function setName(name?: string) {
31 | if (name === null) {
32 | return 'Rain120';
33 | }
34 | return name;
35 | }
36 | ```
37 |
38 | 当然, 你也可以通过短路运算符 `|` 来实现的。
39 |
40 | ```ts
41 | function setName(name?: string) {
42 | return name || 'Rain120';
43 | }
44 | ```
45 |
46 | #### [类型断言](../../type-assertion/README.md)
47 |
48 | ```ts
49 | function setName(name?: string) {
50 | return name!;
51 | }
52 | ```
53 |
54 | 更多操作符相关, 请到 [Here](../../operator/README.md)
55 |
56 | ## 快来耍耍啊
57 |
58 | ### 🌰🌰
59 |
60 |
61 |
62 | ```
63 | // template
64 | ```
65 |
66 | ### 游乐场
67 |
68 |
69 |
70 |
73 |
74 | ### 参考答案
75 |
76 | ```ts
77 | // answer
78 | ```
79 |
80 | ## 参考资料
81 |
82 |
83 |
--------------------------------------------------------------------------------
/docs/zh/advanced-types/type-guard/README.md:
--------------------------------------------------------------------------------
1 | ## 前置知识
2 |
3 | ### 类型谓词
4 |
5 | 在[数学逻辑中](https://en.wikipedia.org/wiki/Mathematical_logic), **[谓词](https://en.wikipedia.org/wiki/Predicate_(mathematical_logic))** 通常被理解为[布尔值函数](https://en.wikipedia.org/wiki/Boolean-valued_function) `P:X → {true, false}`, 称为 **X** 上的谓词。非正式地, 谓词是取决于其变量值的对或错的语句。[\[1\]](https://en.wikipedia.org/wiki/Predicate_(mathematical_logic)#cite_note-1) 可以将其视为返回 `true` 或 `false` 值的运算符或函数。
6 |
7 | **类型谓词** 是一种特殊的返回类型, 它向 `Typescript` 编译器发出信号, 告知特定值是什么类型。**类型谓词** 始终附加到使用单个参数并返回布尔值的函数。类型谓词表示为`argumentName is Type`。
8 |
9 | ```ts
10 | interface Cat {
11 | numberOfLives: number;
12 | }
13 | interface Dog {
14 | isAGoodBoy: boolean;
15 | }
16 |
17 | function isCat(animal: Cat | Dog): animal is Cat {
18 | return typeof animal.numberOfLives === 'number';
19 | }
20 | ```
21 |
22 | ## 定义
23 |
24 | > A type guard is some expression that performs a runtime check that guarantees the type in some scope.
25 |
26 | :::theorem 类型保护
27 | 类型保护就是一些表达式, 它们会在运行时检查以确保在某个作用域里的类型。可以通过 **检测属性、方法或原型, 以确定如何处理值**来实现。
28 | :::
29 |
30 | ## 使用
31 |
32 | ### typeof 类型保护
33 |
34 | ```ts
35 | function padLeft(value: string, padding: string | number) {
36 | if (typeof x === 'number') {
37 | return Array(padding + 1).join(' ') + value;
38 | }
39 | if (typeof x === 'string') {
40 | return padding + value;
41 | }
42 | throw new Error(`Expected string or number, got '${padding}'.`);
43 | }
44 | ```
45 |
46 | ### instanceof 类型保护
47 |
48 | ```ts
49 | interface Padder {
50 | getPaddingString(): string
51 | }
52 |
53 | class SpaceRepeatingPadder implements Padder {
54 | constructor(private numSpaces: number) { }
55 | getPaddingString() {
56 | return Array(this.numSpaces + 1).join(' ');
57 | }
58 | }
59 |
60 | class StringPadder implements Padder {
61 | constructor(private value: string) { }
62 | getPaddingString() {
63 | return this.value;
64 | }
65 | }
66 |
67 | function getRandomPadder() {
68 | return Math.random() < 0.5 ?
69 | new SpaceRepeatingPadder(4) :
70 | new StringPadder(' ');
71 | }
72 |
73 | // Type is 'SpaceRepeatingPadder | StringPadder'
74 | let padder: Padder = getRandomPadder();
75 |
76 | if (padder instanceof SpaceRepeatingPadder) {
77 | padder; // type narrowed to 'SpaceRepeatingPadder'
78 | }
79 | if (padder instanceof StringPadder) {
80 | padder; // type narrowed to 'StringPadder'
81 | }
82 | ```
83 |
84 | `instanceof`的右侧要求是一个构造函数, `TypeScript` 将细化为:
85 |
86 | 1. 此构造函数的 `prototype`属性的类型, 如果它的类型不为 `any`的话
87 | 2. 构造签名所返回的类型的联合
88 |
89 | ### in 类型保护
90 |
91 | ```ts
92 | interface Common {
93 | name: string;
94 | seeSomething: any;
95 | }
96 |
97 | interface Vip {
98 | name: string;
99 | doSomething: any;
100 | }
101 |
102 | type User = Common | Vip;
103 |
104 | function getUserInfo(user: User) {
105 | if ('doSomething' in user) {
106 | // vip
107 | }
108 | if ('seeSomething' in user) {
109 | // common
110 | }
111 | }
112 | ```
113 |
114 | ### 自定义类型保护
115 |
116 | 有时候 `typeof` 和 `instanceof` 没法满足我们的需求, 我们可以通过自定义类型保护来缩窄类型
117 |
118 | ```ts
119 | interface CanLayEggs {
120 | layEggs(): void
121 | }
122 |
123 | interface Bird extends CanLayEggs {
124 | fly(): void
125 | }
126 |
127 | interface Fish extends CanLayEggs {
128 | swim(): void
129 | }
130 |
131 | function getSmallPet(): Fish | Bird {
132 | const fish: Fish = {}
133 | return fish
134 | }
135 |
136 | const pet = getSmallPet()
137 |
138 | // 使用 自定义的类型保护
139 | function isFish(pet: Fish | Bird): pet is Fish {
140 | return (pet).swim !== undefined
141 | }
142 |
143 | if (isFish(pet)) {
144 | pet.swim()
145 | } else {
146 | pet.fly()
147 | }
148 | ```
149 |
150 | ## 快来耍耍啊
151 |
152 | ### 🌰🌰
153 |
154 |
155 |
156 | ```
157 | // template
158 | ```
159 |
160 | ### 游乐场
161 |
162 |
163 |
164 |
167 |
168 | ### 参考答案
169 |
170 | ```ts
171 | // answer
172 | ```
173 |
174 | ## 参考资料
175 |
176 | [handbook - type-guards-and-differentiating-types](https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types)
177 |
178 | [type-guard](https://basarat.gitbook.io/typescript/type-system/typeguard)
179 |
180 | [aha-understanding-typescript-s-type-predicates](https://dev.to/daveturissini/aha-understanding-typescript-s-type-predicates-40ha)
181 |
182 | [typescript-type-predicates](https://fettblog.eu/typescript-type-predicates/)
--------------------------------------------------------------------------------
/docs/zh/advanced-types/union-types/README.md:
--------------------------------------------------------------------------------
1 | ## 定义
2 |
3 | :::theorem 联合类型
4 | 联合类型具有 **或** 关系的多个类型组合而成, 只要满足其中一个类型即可。当你不确定某个对象的值是什么类型时就可以使用 **联合类型**。
5 | :::
6 |
7 | **Note:** 联合类型是 **且** 的关系, 即 $A \cap B$, 使用 `|` 运算符 。
8 |
9 | ## Nullable 与 联合类型
10 |
11 | ```ts
12 | let name: string = 'Rain120'
13 |
14 | name = null;
15 | name = undefined;
16 |
17 | console.log(name.toString())
18 |
19 | // ====>
20 |
21 | let name: string | null | undefined;
22 |
23 | ```
24 |
25 | 更多尝试 [Here](https://www.typescriptlang.org/play/#code/DYUwLgBAdghgtiAXBAzmATgSygcwgXggHIAlGbARgCYAGIgKHtgQOgFdhgBuJ+EVtlAAmIAGbYQQnvQDGAeygo5oAHTA5OABTMQKsHIDKGbFoCUpoA)
26 |
27 | 从类型上看, `Nullable` 类型相当于原类型与`null | undefined`组成的联合类型, 从上示例意味着, **类型检查** 并不可靠, 针对空类型的 **潜在问题**, `TypeScript` 提供了`--strictNullChecks`选项, 开启之后会严格检查空类型。
28 |
29 | 更多 `Nullable` 相关请到 [Here](../nullable/README.md)
30 |
31 | ## 使用
32 |
33 | ```ts
34 | interface Boy {
35 | hair: boolean;
36 | tall: boolean;
37 | }
38 |
39 | interface Girl {
40 | hair: boolean;
41 | cute: boolean;
42 | }
43 |
44 | type Person = Boy | Girl
45 |
46 | const someone: Person = {
47 | hair: true
48 | }
49 | ```
50 |
51 | ## 快来耍耍啊
52 |
53 | ### 🌰🌰
54 |
55 |
56 |
57 | ```
58 | // template
59 | ```
60 |
61 | ### 游乐场
62 |
63 |
64 |
65 |
68 |
69 | ### 参考答案
70 |
71 | ```ts
72 | // answer
73 | ```
74 |
75 | ## 参考资料
76 |
77 | [handbook - union-types](https://www.typescriptlang.org/docs/handbook/advanced-types.html#union-types)
78 |
79 | [unions](https://basarat.gitbook.io/typescript/type-system/discriminated-unions)
80 |
81 | [数学公式参考](https://latexlive.com/)
82 |
--------------------------------------------------------------------------------
/docs/zh/array/README.md:
--------------------------------------------------------------------------------
1 | ## 定义
2 |
3 | `TypeScript` 像 `JavaScript` 一样可以操作数组元素。
4 |
5 | ## 使用
6 |
7 | 有以下几种方式可以定义数组。
8 |
9 | ### 元素类型 + []
10 |
11 | ```ts
12 | const list: number[] = [1, 2, 3];
13 | ```
14 |
15 | ### 数组泛型, `Array<元素类型>`
16 |
17 | ```ts
18 | const list: Array = [1, 2, 3];
19 | ```
20 |
21 | 泛型相关, 请到 [Here](../generics/README.md)
22 |
23 | ### 接口
24 |
25 | ```ts
26 | interface List {
27 | [index: number]: number;
28 | }
29 |
30 | const list: List = [1, 2, 3];
31 | ```
32 |
33 | ## 快来耍耍啊
34 |
35 | ### 🌰🌰
36 |
37 |
38 |
39 | ```
40 | // template
41 | ```
42 |
43 | ### 游乐场
44 |
45 |
46 |
47 |
50 |
51 | ### 参考答案
52 |
53 | ```ts
54 | // answer
55 | ```
56 |
57 | ## 参考资料
58 |
59 | [Handbook - array](https://www.typescriptlang.org/docs/handbook/basic-types.html#array)
60 |
61 | [数组的类型](https://ts.xcatliu.com/basics/type-of-array.html)
--------------------------------------------------------------------------------
/docs/zh/basic/README.md:
--------------------------------------------------------------------------------
1 | ## Boolean 类型
2 |
3 | ```ts
4 | const handsome: boolean = true;
5 | ```
6 |
7 | ## Number 类型
8 |
9 | ```ts
10 | const age: number = 18;
11 | ```
12 |
13 | ## String 类型
14 |
15 | ```ts
16 | const name: string = 'Rain120;
17 | ```
18 |
19 | ## Array 类型
20 |
21 | ```ts
22 | const travel_cities: string[] = [
23 | 'beijing',
24 | 'shanghai',
25 | 'nanjing',
26 | 'hangzhou',
27 | 'wuhan',
28 | 'changsha',
29 | 'jilin',
30 | 'shenyang'
31 | ];
32 |
33 | // 使用数组泛型
34 | const travel_cities: Array = [
35 | 'beijing',
36 | 'shanghai',
37 | 'nanjing',
38 | 'hangzhou',
39 | 'wuhan',
40 | 'changsha',
41 | 'jilin',
42 | 'shenyang'
43 | ];
44 | ```
45 |
46 | ## Tuple 类型
47 |
48 | 元组类型允许表示一个 **已知元素数量和类型** 的 **数组**, 各元素的类型不必相同。 比如, 你可以定义一对值分别为 `string` 和 `number` 类型的元组。
49 |
50 | ```ts
51 | let age: [number, string];
52 |
53 | age = [18, '18']; // ok
54 |
55 | age = ['18', 18]; // error
56 |
57 | ```
58 |
59 | ### 初始化
60 |
61 | 在元组初始化的时候, 我们还必须提供每个属性的值, 不然也会出现错误。
62 |
63 | ```ts
64 | age = [18];
65 |
66 | // Property '1' is missing in type '[string]' but required in type '[number, string]'.
67 | ```
68 |
69 | ### 越界元素
70 |
71 | 当添加越界的元素时, 它的类型会被限制为元组中每个类型的联合类型。
72 |
73 | ```ts
74 | age.push(true);
75 |
76 | // Argument of type 'true' is not assignable to parameter of type 'number | string'.
77 | ```
78 |
79 | ## Enum 类型
80 |
81 | 使用枚举我们可以定义一些带名字的常量。 使用枚举可以清晰地表达意图或创建一组有区别的用例。
82 |
83 | ### 数字枚举
84 |
85 | ```ts
86 | enum Gender {
87 | FEMALE,
88 | MALE,
89 | }
90 |
91 | console.log(Gender.FEMALE); // 0
92 | ```
93 |
94 | 转换成 `ES5`
95 |
96 | ```js
97 | "use strict";
98 | var Gender;
99 | (function (Gender) {
100 | Gender[Gender["FEMALE"] = 0] = "FEMALE";
101 | Gender[Gender["MALE"] = 1] = "MALE";
102 | })(Gender || (Gender = {}));
103 | ```
104 |
105 | [Go Demo](https://www.typescriptlang.org/play?#code/KYOwrgtgBA4qAmwBOUDeAoKUBiBRAsgIIAyuANJlEaRQL5A)
106 |
107 | 默认情况下, 从`0`开始为元素编号。 你也可以手动的指定成员的数值。比如
108 |
109 | ```ts
110 | enum Gender {
111 | FEMALE = 1,
112 | MALE,
113 | }
114 |
115 | console.log(Gender.FEMALE); // 1
116 | ```
117 |
118 | 转换成 `ES5`
119 |
120 | ```js
121 | "use strict";
122 | var Gender;
123 | (function (Gender) {
124 | Gender[Gender["FEMALE"] = 1] = "FEMALE";
125 | Gender[Gender["MALE"] = 2] = "MALE";
126 | })(Gender || (Gender = {}));
127 | ```
128 |
129 | [Go Demo](https://www.typescriptlang.org/play?#code/KYOwrgtgBA4qAmwBOUDeAoKUBiBRAsgIIAyuUAvFAIwA0mURpdAvkA)
130 |
131 | ### 字符串枚举
132 |
133 | 在一个字符串枚举里, 每个成员都必须用字符串字面量, 或另外一个字符串枚举成员进行初始化。
134 |
135 | ```ts
136 | enum Gender {
137 | FEMALE = 'FEMALE',
138 | MALE = 'MALE',
139 | }
140 |
141 | console.log(Gender.FEMALE); // FEMALE
142 | ```
143 |
144 | 转换成 `ES5`
145 |
146 | ```js
147 | "use strict";
148 | var Gender;
149 | (function (Gender) {
150 | Gender["FEMALE"] = "FEMALE";
151 | Gender["MALE"] = "MALE";
152 | })(Gender || (Gender = {}));
153 |
154 | ```
155 |
156 | [Go Demo](https://www.typescriptlang.org/play?#code/KYOwrgtgBA4qAmwBOUDeAoKUBiBRAsgIIAyuUAvFAOR5GlUA0mUdZlVrj6AvkA)
157 |
158 | ### 异构枚举
159 |
160 | 异构枚举的成员值是数字和字符串的混合
161 |
162 | ```ts
163 | enum Enum {
164 | A,
165 | B,
166 | C = "C",
167 | D = "D",
168 | E = 8,
169 | F,
170 | }
171 |
172 | console.log(Enum.C); // C
173 | console.log(Enum.E); // 8
174 | ```
175 |
176 | 转换成 `ES5`
177 |
178 | ```js
179 | "use strict";
180 | var Enum;
181 | (function (Enum) {
182 | Enum[Enum["A"] = 0] = "A";
183 | Enum[Enum["B"] = 1] = "B";
184 | Enum["C"] = "C";
185 | Enum["D"] = "D";
186 | Enum[Enum["E"] = 8] = "E";
187 | Enum[Enum["F"] = 9] = "F";
188 | })(Enum || (Enum = {}));
189 | ```
190 |
191 | [Go Demo](https://www.typescriptlang.org/play?#code/KYOwrgtgBAou0G8BQUoEEA0KoCEuoGEoBeKAIgLPygBETyarsZ6AOagMSwF8kg)
192 |
193 | ## Any 类型
194 |
195 | 有时候, 我们会想要为那些在编程阶段还不清楚类型的变量指定一个类型, 这些值可能来自于动态的内容。
196 |
197 | 在 `TypeScript` 中, 任何类型都可以被归为 `any` 类型。这让 `any`类型成为了类型系统的 [**顶级类型**](https://en.wikipedia.org/wiki/Top_type)(也被称作 **全局超级类型**)。
198 |
199 | 使用 `any` 类型的变量能够兼容所有的类型, `typescript` 将不会对他做任何类型检查, 所以我们将无法对其做类型保护, 这样我们就会很容易地编写类型正确, 但在运行时有问题的代码。
200 |
201 | 例如:
202 |
203 | ```ts
204 | let value: any;
205 |
206 | value = true; // OK
207 | value = 42; // OK
208 | value = "Hello World"; // OK
209 | value = []; // OK
210 | value = {}; // OK
211 | value = Math.random; // OK
212 | value = null; // OK
213 | value = undefined; // OK
214 | value = new TypeError(); // OK
215 | value = Symbol("type"); // OK
216 | ```
217 |
218 | `any`类型本质上是类型系统的一个逃逸舱。作为开发者, 这给了我们很大的自由:TypeScript允许我们对 `any`类型的值执行任何操作, 而无需事先执行任何形式的检查。
219 |
220 | 在上述例子中, 变量 `value`被定义成类型 `any`。也是因此, `TypeScript` 认为以下所有操作都是类型正确的:
221 |
222 | ```ts
223 | let value: any;
224 |
225 | value.foo.bar; // OK
226 | value.trim(); // OK
227 | value(); // OK
228 | new value(); // OK
229 | value[0][1]; // OK
230 | ```
231 |
232 | 这许多场景下, 这样的机制都太宽松了。使用`any`类型, 可以很容易地编写类型正确但是执行异常的代码。如果我们使用 `any`类型, 就无法享受 `TypeScript` 大量的保护机制。
233 |
234 | ## Unknown 类型
235 |
236 | `TypeScript 3.0` 引入了新的`unknown` 类型, 它是 `any` 类型对应的安全类型。
237 |
238 | `unknown` 和 `any` 的主要区别是 `unknown` 类型会更加严格:在对 `unknown` 类型的值执行大多数操作之前, 我们必须进行某种形式的检查。而在对 `any` 类型的值执行操作之前, 我们不必进行任何检查。
239 |
240 | ```ts
241 | let value: any;
242 |
243 | value = true; // OK
244 | value = 42; // OK
245 | value = "Hello World"; // OK
246 | value = []; // OK
247 | value = {}; // OK
248 | value = Math.random; // OK
249 | value = null; // OK
250 | value = undefined; // OK
251 | value = new TypeError(); // OK
252 | value = Symbol("type"); // OK
253 | ```
254 |
255 | 对 `value`变量的所有赋值都被认为是类型正确的。
256 |
257 | 当我们尝试将类型为 `unknown`的值赋值给其他类型的变量时会发生什么?
258 |
259 | ```ts
260 | let value: unknown;
261 |
262 | let value1: unknown = value; // OK
263 | let value2: any = value; // OK
264 | let value3: boolean = value; // Error
265 | let value4: number = value; // Error
266 | let value5: string = value; // Error
267 | let value6: object = value; // Error
268 | let value7: any[] = value; // Error
269 | let value8: Function = value; // Error
270 | ```
271 |
272 | `unknown`类型只能被赋值给 `any`类型和 `unknown`类型本身。直观的说, 这是有道理的:只有能够保存任意类型值的容器才能保存 `unknown`类型的值。毕竟我们不知道变量 `value`中存储了什么类型的值。
273 |
274 | 现在让我们看看当我们尝试对类型为 `unknown`的值执行操作时会发生什么。以下是我们之前看过的相同操作:
275 |
276 | ```ts
277 | let value: unknown;
278 |
279 | value.foo.bar; // Error
280 | value.trim(); // Error
281 | value(); // Error
282 | new value(); // Error
283 | value[0][1]; // Error
284 | ```
285 |
286 | 将 `value`变量类型设置为 `unknown`后, 这些操作都不再被认为是类型正确的。通过改变 `any`类型到 `unknown`类型, 我们的默认设置从允许一切翻转式的改变成了几乎什么都不允许。
287 |
288 | 这是 `unknown`类型的主要价值主张:`TypeScript` 不允许我们对类型为 `unknown`的值执行任意操作。相反, 我们必须首先执行某种类型检查以缩小我们正在使用的值的类型范围。
289 |
290 | ## Null & Undefined 类型
291 |
292 | `undefined` 和 `null` 两者各自有自己的类型分别叫做 `undefined` 和 `null`。
293 |
294 | ```ts
295 | let u: undefined = undefined;
296 | let n: null = null;
297 | ```
298 |
299 | 默认情况下`null`和`undefined`是所有类型的子类型。 就是说你可以把 `null`和`undefined`赋值给`number`类型的变量。**当你指定了`--strictNullChecks`标记, `null`和`undefined`只能赋值给`void`和它们各自的类型。**
300 |
301 | ## Void 类型
302 |
303 | 某种程度上来说, `void` 类型像是与any类型相反, 它**表示没有任何类型**。 当一个函数没有返回值时, 你通常会见到其返回值类型是 `void` :
304 |
305 | ```ts
306 | function warnUser(): void {
307 | console.log("This is my warning message");
308 | }
309 |
310 | ```
311 |
312 | 声明一个 `void` 类型的变量没有什么大用, 因为你只能为它赋予 `undefined` 和 `null`:
313 |
314 | ```ts
315 | let unusable: void = undefined;
316 | ```
317 |
318 | ## Never 类型
319 |
320 | `never`类型表示的是那些**永不存在的值的类型**。例如, `never` 类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型。
321 |
322 | ```ts
323 | // 返回never的函数必须存在无法达到的终点
324 | function error(message: string): never {
325 | throw new Error(message);
326 | }
327 |
328 | // 推断的返回值类型为never
329 | function fail() {
330 | return error("Something failed");
331 | }
332 |
333 | // 返回never的函数必须存在无法达到的终点
334 | function infiniteLoop(): never {
335 | while (true) {
336 | }
337 | }
338 | ```
339 |
340 | `never`类型是任何类型的子类型, 也可以赋值给任何类型, 但它不可以被其他类型赋值, 它**只能被赋值**给另外一个 `never` 类型, `any` 也不行, 。
341 |
342 | ```ts
343 | function neverKnow(): never {
344 | throw new Error('error');
345 | }
346 |
347 | let idk: never = neverKnow();
348 |
349 | idk = "I don't know";
350 | // Type '"I don't know"' is not assignable to type 'never'.
351 | ```
352 |
353 | [Go Demo](https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABGApgNxQJwNJjgdwAoBKALmXS0QG8AoRRKAC0wIv0QFFNXNCByLL37EA3LQC+tWgBsUURDAAmAa3KoMmRAF4Km3ARLjaylTsQAiAJKIlCfgpV58F0UA)
354 |
355 | 在没有开启 **--strictNullChecks** 的前提下使用 `never` 避免出现新增了联合类型没有对应的实现, 目的就是写出类型绝对安全的代码。
356 |
357 | 举个具体点的例子, 当你有一个 `union type`:
358 |
359 | ```ts
360 | interface Foo {
361 | type: 'foo'
362 | }
363 |
364 | interface Bar {
365 | type: 'bar'
366 | }
367 |
368 | type All = Foo | Bar
369 | ```
370 |
371 | 在 `switch` 当中判断 `type`, `TS` 是可以收窄类型的 `(discriminated union)`:
372 |
373 | ```ts
374 | function handleValue(val: All) {
375 | switch (val.type) {
376 | case 'foo':
377 | // 这里 val 被收窄为 Foo
378 | break
379 | case 'bar':
380 | // val 在这里是 Bar
381 | break
382 | default:
383 | // val 在这里是 never
384 | const exhaustiveCheck: never = val
385 | break
386 | }
387 | }
388 | ```
389 |
390 | 注意在 `default` 里面我们把被收窄为 `never` 的 `val` 赋值给一个显式声明为 `never` 的变量。如果一切逻辑正确, 那么这里应该能够编译通过。但是假如后来有一天你的同事改了 All 的类型:
391 |
392 | ```ts
393 | type All = Foo | Bar | Baz
394 | ```
395 |
396 | 然而他忘记了在 `handleValue` 里面加上针对 `Baz` 的处理逻辑, 这个时候在 `default branch` 里面 val 会被收窄为 Baz, 导致无法赋值给 `never`, 产生一个编译错误。所以通过这个办法, 你可以确保 `handleValue` 总是穷尽 `(exhaust)` 了所有 `All` 的可能类型。
397 |
398 | [TypeScript中的never类型具体有什么用? - 尤雨溪的回答 - 知乎](https://www.zhihu.com/question/354601204/answer/888551021)
399 |
400 | [Typescript Handbook 详尽检查](https://www.typescriptlang.org/docs/handbook/advanced-types.html#exhaustiveness-checking)
401 |
402 | ### Never 与 Void 的区别
403 |
404 | - `void`表示没有任何类型, `never`表示永不存在的值的类型
405 | - `--strictNullChecking=false`时, `void` 可以被赋值为任意类型, `never`只能被赋值为 `never`
406 |
407 |
410 |
411 | ## 快来耍耍啊
412 |
413 | ### 🌰🌰
414 |
415 | 定义一个人员信息, 包括姓名, 年龄等信息。
416 |
417 | ```
418 | const profile = {}
419 | ```
420 |
421 | ### 游乐场
422 |
423 |
424 |
425 |
429 |
430 |
433 |
434 |
435 |
436 | ### 参考答案
437 |
438 | ```ts
439 | interface Profile {
440 | name: string;
441 | age: number | string;
442 | }
443 | ```
444 |
445 | ## 参考资料
446 |
447 | [Typescript Basic Types](https://www.typescriptlang.org/docs/handbook/basic-types.html) -> [中文](https://www.tslang.cn/docs/handbook/basic-types.html)
448 |
449 | [Typescript Handbook](https://www.typescriptlang.org/docs/handbook/basic-types.html)
450 |
451 | [the-unknown-type-in-typescript](https://mariusschulz.com/blog/the-unknown-type-in-typescript)
452 |
--------------------------------------------------------------------------------
/docs/zh/blog/README.md:
--------------------------------------------------------------------------------
1 | ## 博客 & 学习网站
2 |
3 | - [TypeScript Github](https://github.com/Microsoft/TypeScript)
4 | - [Typescritp tsconfig](https://www.typescriptlang.org/tsconfig)
5 | - [Typescript Handbook](https://www.typescriptlang.org/docs/handbook/intro.html)
6 | - [Typescript Playground](https://www.typescriptlang.org/play): `TypeScript` 游乐场
7 | - [《TypeScript Deep Dive》](https://basarat.gitbook.io/typescript/) 是一本很好的开源书, 从基础到深入, 很全面的阐述了 `TypeScript` 的各种魔法, 不管你是新手, 还是老鸟, 它都将适应你。此外, 它不同于 `TypeScript` 官方给出的文档(当然 `TypeScript` 给出的文档是很好的), 在此书中, 结合实际应用下的场景用例, 你将能更深入的理解 `TypeScript`。[中文版](https://jkchao.github.io/typescript-book-chinese/)
8 | - [awesome-typescript](https://github.com/semlinker/awesome-typescript) 收集了很多 `Typescript` 的相关学习资料。
9 | - [typescript-cheatsheets-react](https://github.com/typescript-cheatsheets/react)
10 |
11 | ## Tips
12 |
13 | - [一些 Typescript的小知识](https://www.yuque.com/arvinxx-fe/typescript)
14 |
15 | ## Pdf & 书籍资料
16 |
17 | - [TypeScript入门指南案例教程(阮一峰).pdf](https://github.com/Rain120/typescript-guide/releases/tag/0.0.1)
18 |
--------------------------------------------------------------------------------
/docs/zh/built-in-objects/README.md:
--------------------------------------------------------------------------------
1 | ## 定义
2 |
3 | **内置对象** 是指根据标准`(ECMAScript, DOM, BOM 等其他标准)`在全局作用域 `(Global)` 上已经存在定义的对象。`JavaScript` 中有很多 [标准内置对象](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects), 它们可以直接在 `TypeScript` 中当做定义好了的类型。
4 |
5 | ## ECMAScript 的内置对象
6 |
7 | 从 `MDN` 中 [JavaScript 标准内置对象](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects) 中, 我们知道 `JavaScript` 有很多 **内置对象**, 比如 `String`, `Boolean`, `Date`等等。那在 `Typescript` 中, 我们改怎么取定义这些类型呢?
8 |
9 | ```ts
10 | // https://github.com/microsoft/TypeScript/blob/2dd7a4bf939ffac4002ea9c76651166ba457ac70/src/lib/es5.d.ts#L497
11 | const name: String = new String('Rain120');
12 |
13 | // https://github.com/microsoft/TypeScript/blob/2dd7a4bf939ffac4002ea9c76651166ba457ac70/src/lib/es5.d.ts#L509
14 | const handsome: Boolean = new Boolean(true);
15 |
16 | // https://github.com/microsoft/TypeScript/blob/2dd7a4bf939ffac4002ea9c76651166ba457ac70/src/lib/es5.d.ts#L709
17 | const birthday_month: Date = new Date('11');
18 | ```
19 |
20 | 这里我们使用 `Typescript` 来实现下 `Boolean` 定义。
21 |
22 | ```ts
23 |
24 | interface Boolean {
25 | /** Returns the primitive value of the specified object. */
26 | valueOf(): boolean;
27 | }
28 |
29 | interface BooleanConstructor {
30 | new(value?: any): Boolean;
31 | (value?: T): boolean;
32 | readonly prototype: Boolean;
33 | }
34 |
35 | declare var Boolean: BooleanConstructor;
36 | ```
37 |
38 | 更多`ES5` 相关的内置对象定义在这👉👉👉 [Here on Typescript Definition](https://github.com/microsoft/TypeScript/blob/master/src/lib/es5.d.ts)
39 |
40 | ## DOM & BOM 的内置对象
41 |
42 | [DOM (文档对象模型)](https://developer.mozilla.org/zh-CN/docs/Web/API/Document_Object_Model) 和 `BOM (浏览器对象模型)`提供了很多内置对象,比如 `NodeList`, `HTMLElemnt` 等内置对象。
43 |
44 | ```ts
45 | // https://github.com/microsoft/TypeScript/blob/2dd7a4bf939ffac4002ea9c76651166ba457ac70/src/lib/dom.generated.d.ts#L10984
46 | const divs: NodeList = document.querySelectorAll('div');
47 |
48 | // https://github.com/microsoft/TypeScript/blob/master/src/lib/dom.generated.d.ts#L10984
49 | interface Window {
50 | history: History
51 | }
52 |
53 | console.log(window?.history)
54 | ```
55 |
56 |
57 |
58 | 更多`DOM` 相关的内置对象定义在这👉👉👉 [Here on Typescript Definition](https://github.com/microsoft/TypeScript/blob/master/src/lib/dom.generated.d.ts)
59 |
60 | ## 包内置对象
61 |
62 | 当你使用 `Typescript` 写 `Node` 时, 你会发现很多都没有语法提示,这时,你需要执行下面的命令
63 |
64 | ```sh
65 | npm install @types/node
66 | ```
67 |
68 | 在 `@types/node` 已经将 `node` 所有的内置对象的 `typescript` 的定义都定义好了,当前很多 `typescript` 包也都有这类的 `type` 定义, 你可以通过下列命令来 **查询是否存在类型定义** 且 **安装类型定义文件**
69 |
70 | ```sh
71 | # 查询是否存在类型定义
72 | npm search @types/xxx
73 |
74 | # 安装
75 | npm install @types/xxx
76 | ```
77 |
78 | ## 快来耍耍啊
79 |
80 | ### 🌰🌰
81 |
82 |
83 |
84 | ```
85 | // template
86 | ```
87 |
88 | ### 游乐场
89 |
90 |
91 |
92 |
95 |
96 | ### 参考答案
97 |
98 | ```ts
99 | // answer
100 | ```
101 |
102 | ## 参考资料
103 |
104 | [Typescript 核心文件库](https://github.com/Microsoft/TypeScript/tree/master/src/lib)
105 |
106 | [JavaScript 标准内置对象](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects)
107 |
108 | [文档对象模型 DOM](https://developer.mozilla.org/zh-CN/docs/Web/API/Document_Object_Model)
109 |
110 | [MDN Window](https://developer.mozilla.org/zh-CN/docs/Web/API/Window)
--------------------------------------------------------------------------------
/docs/zh/class/README.md:
--------------------------------------------------------------------------------
1 | ## 定义
2 |
3 | 类(英语: `class`)在[**面向对象编程(oop)**](https://zh.wikipedia.org/zh-cn/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1)中是一种面向对象计算机编程语言的构造, 是创建对象的蓝图, 描述了所创建的对象共同的属性和方法。
4 |
5 | `JavaScript` 语言中, 生成实例对象的传统方法是通过构造函数。`ES6` 提供了更接近传统语言的写法, 引入了 `Class(类)`这个概念, 作为对象的模板。通过 `class` 关键字, 可以定义类。
6 |
7 | `TypeScript` 除了实现了所有 `ES6` 中的类的功能以外,还添加了一些新的用法。
8 |
9 | ### 类的概念
10 |
11 | - 对象
12 |
13 | 类的实例, 通过 `new`实例化
14 |
15 | - [面向对象三大特性](#面向对象的三大特性)
16 |
17 | 👇👇👇 [Here](#面向对象的三大特性)
18 |
19 | - [存取器](#存取器)
20 |
21 | `getter`: 对属性的取值行为
22 |
23 | `setter`: 对属性的赋值行为
24 |
25 | - [修饰符](#修饰符)
26 |
27 | `public`: 修饰**公有**属性和方法 `(默认)`,可以在任何地方被访问到
28 |
29 | `protected`: 修饰**保护**属性和方法,在子类中也是允许被访问的
30 |
31 | `private`: 修饰**私有**属性和方法,不能在声明它的类的外部访问
32 |
33 | - [静态属性 & 方法 `static`](#静态属性-方法)
34 |
35 | **只能**通过类访问的属性 `or` 方法。
36 |
37 | - [抽象类](#抽象类)
38 |
39 | 抽象类`(absctract)`是供其他类继承的基类,**抽象类不允许被实例化**。抽象类中的抽象方法**必须在子类中被实现**
40 |
41 | - [接口](#把类当接口使用)
42 |
43 | 不同类之间公有的属性或方法,可以抽象成一个接口。接口可以被类实现 `(implements)`。**一个类只能继承自另一个类,但是可以实现多个接口**
44 |
45 | ## 面向对象的三大特性
46 |
47 | ### 封装
48 |
49 | 利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,**数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节**,只保留一些对外接口使之与外部发生联系。
50 |
51 | ### 继承
52 |
53 | 子类获取父类的所有属性和行为`(除了父类中用 private 修饰的变量和方法)`。
54 |
55 | ### 多态
56 |
57 | **多种不同的实现方式**即为多态, 它允许方法重名,参数或返回值可以是父类型传入或返回。
58 |
59 | ## 类的好处
60 |
61 | - 对象提供了模型化和信息隐藏的好处。
62 |
63 | - 类提供了[可重复使用性](https://zh.wikipedia.org/w/index.php?title=可重複使用性&action=edit&redlink=1)的好处。
64 |
65 | ## 使用
66 |
67 | ### public(公有) & protected(保护) & private(私有) 修饰符
68 |
69 | #### public
70 |
71 | 修饰**公有**属性和方法 `(默认)`,可以在任何地方被访问到
72 |
73 | ```ts
74 | class Animal {
75 | public name: string;
76 | public constructor(theName: string) { this.name = theName; }
77 | public move(distanceInMeters: number) {
78 | console.log(`${this.name} moved ${distanceInMeters}m.`);
79 | }
80 | }
81 | ```
82 |
83 | [Playground](https://www.typescriptlang.org/play?#code/MYGwhgzhAECCB2BLAtmE0DeAoavoAcBXAIxEWGnjGQFMAuaCAFwCdF4BzAbhzyNPLRgAe3jMWhYE2EsAFEwAWNAHLV6jVuw4BKTNEWIIAOiq1oAXn1LVtLtAC+vXPzIVkwgG41ZAE0NMweGAaAEl4AFkaJhoWCAZ4QmRiGN1sPHShUQhhEBojEGEOWQADABIMA2NTGntody8faHK-ZkDgsMjo2PtkI2LtHnTHeyA)
84 |
85 | #### protected
86 |
87 | 修饰**保护**属性和方法,在子类中也是允许被访问的
88 |
89 | ```ts
90 | class Person {
91 | protected name: string;
92 | constructor(name: string) { this.name = name; }
93 | }
94 |
95 | class Employee extends Person {
96 | private department: string;
97 |
98 | constructor(name: string, department: string) {
99 | super(name)
100 | this.department = department;
101 | }
102 |
103 | public getElevatorPitch() {
104 | return `Hello, my name is ${this.name} and I work in ${this.department}.`;
105 | }
106 | }
107 |
108 | let rainy = new Employee("Rain", "120");
109 | console.log(rainy.getElevatorPitch());
110 | console.log(rainy.name); // 错误
111 | ```
112 |
113 | [Playground](https://www.typescriptlang.org/play?#code/MYGwhgzhAEAKCmAnCB7AdtA3gKGn6ADoigC7zBkAm0aYAtvAFzQQmICWaA5gNy77B0rRAFcKKRAApaDZsM5cAlFmgkAFuwgA6GfGgBeGvXg9oAX2wXsoSDACidAiBQBPeHvgAPMmkowEyOhY-HhE7ABuYGTQlPAEYIgkDGgkcmwKfCHQgmjCYiQS0sZpHNwANDFxCUnwKSUKyjj4zSwiBEhFDIpZzeqaWrHxickkBpVDNSl8zVbNBCIARiDswNBc8CR2IPCRBYiw7CTAapKNPfiIGyKIGAAGABLwIM4VdC5GDNCa0AAkmH3aXRmaBgXzQACS0AA7hIANZfDB-AEDKrDWokMxaW7TfAWKzbUaIMCcd6GNDwKHQBxOVzuSQAIgASsS0PSKvSAIwAJgADPTFHwcqhtlpnFxJESSVp1pttrsJAcjidFALrEIUCKxRKWS4dMYBdAAPSG6CATFTAPfRQA)
114 |
115 | #### private
116 |
117 | 修饰**私有**属性和方法,不能在声明它的类的外部访问
118 |
119 | ```ts
120 | class Animal {
121 | private name: string;
122 | constructor(theName: string) { this.name = theName; }
123 | }
124 |
125 | class Cat extends Animal {
126 | constructor() { super("Cat"); }
127 | }
128 |
129 | class Employee {
130 | private name: string;
131 | constructor(theName: string) { this.name = theName; }
132 | }
133 |
134 | let animal = new Animal("Dog");
135 | let cat = new Cat();
136 | let employee = new Employee("Rain120");
137 |
138 | animal = cat;
139 | animal = employee; // 错误: Animal 与 Employee 不兼容.
140 | ```
141 |
142 | [Playground](https://www.typescriptlang.org/play?#code/MYGwhgzhAECCB2BLAtmE0DeAoavoAcAnRANzABcBTaeMZSgLmgnOPgHMBuHPYAe3gtCAV2Dk+hABTkAFpQBydRs1aIOASkzRZiCADpa9aAF5tcxfU7QAvlltZQkGAGEK0SgA8q8ACYwEKGiYPLj8gqyi4lKaGMzC+JRSAESu5EnqVrb2jlDQAKLI+CB8AJ6U1Nh4BMRkVDRKTEJqXCHQYUKREtLmDSps7DFmugZKJmYKSpl2WFgglOTQYEio6KbwlADucMtokkkAInzs6dxzC8Bua5vQqZIZs-PuhcVl1FdbBUWl5XsASmBqACMACYAAwnGZLQKrNoUbhQlZjSjPb6UKwAenR0EAmKmAe+imAFEYA4OXyKNe0EAsHKAH0VAJ3aeiAA)
143 |
144 | ### readonly 修饰符
145 |
146 | #### 属性
147 |
148 | 将属性设置为只读的。 **只读属性必须在声明时或构造函数里被初始化**。
149 |
150 | ```ts
151 | class Octopus {
152 | readonly name: string;
153 | readonly numberOfLegs: number = 8;
154 | constructor (theName: string) {
155 | this.name = theName;
156 | }
157 | }
158 | let dad = new Octopus("Man with the 8 strong legs");
159 | dad.name = "Man with the 3-piece suit"; // 错误! name 是只读的.
160 | ```
161 |
162 | [Playground](https://www.typescriptlang.org/play?#code/MYGwhgzhAEDywBcD2AHArjA3gKGn6ATgKZgAmSAdiAJ7QVgC2RAXNBAgQJYUDmA3LnzEylGnTQMARkQKwAZgBkiPCKwoTpBaAF5oADgH5owSuwJpESLQAoEACyIA5RizYduPAJTQcRo-c4IADp6Jh1oeycXQ3wAX2x4kCIEaFIycIoiAHc4S3QIawAiAFkwCmgsznsIh303AkoeaCSVQs8BNNIQl3CSsoqquxqiaABmAFoUTiJgEYg0KsK+IA)
163 |
164 | #### 参数
165 |
166 | ```ts
167 | class Octopus {
168 | readonly numberOfLegs: number = 8;
169 | constructor(readonly name: string) {
170 | }
171 | }
172 | ```
173 |
174 | [Playground](https://www.typescriptlang.org/play?#code/MYGwhgzhAEDywBcD2AHArjA3gKGn6ATgKZgAmSAdiAJ7QVoC2ARkQbAGYAyRA5hAFx1GLAtAC80ABwBuXPmCUICAmkRICACmJlKNOmAZFBSggEsKPAJTQc+aAF9s9oA)
175 |
176 | ### 存取器
177 |
178 | ```ts
179 | class Employee {
180 | private _fullName: string = '';
181 |
182 | constructor(_fullName: string) {}
183 |
184 | get fullName(): string {
185 | return this._fullName;
186 | }
187 |
188 | set fullName(newName: string) {
189 | this._fullName = newName;
190 | }
191 | }
192 |
193 | let employee = new Employee('Rainy');
194 | employee.fullName = "Rain120";
195 | console.log(employee.fullName)
196 | ```
197 |
198 | [Playground](https://www.typescriptlang.org/play?#code/MYGwhgzhAECiC2AHEB7AngUw9A3gKGkOkQCcBLANzABdsB9AMwFcQQA5MeDALmgmvIA7AObQAvNADkkgNx48ASGApB-Ek2DUUJABSMW7Tjz4CyIgJS4AvvKLRhGatGasOXHed5qzo-HbskjkwkgtDUABZkEAB0+q5GcnY2BEQQjs4Gbhg6ghgA7llepha4Kf5hkTFxhlzi0LkFCWXQNskg6RhIqJjYEg1wXehYOpIASmBmaJLmcp3IQxjRLjW90ABE42YAjABMAAxrcsqqKO3RqMI6c91YS5lG5kA)
199 |
200 | **Note:**
201 |
202 | - 存取器要求你将编译器设置为输出 `ECMAScript 5`或更高。 不支持降级到`ECMAScript 3`。
203 | - **只带有 `get`不带有 `set`的存取器**自动被推断为 `readonly`。 这在从代码生成 `.d.ts`文件时是有帮助的,因为利用这个属性的用户会看到不允许够改变它的值。
204 |
205 | ### 静态属性 & 方法
206 |
207 | 只能通过类来访问,实例不行
208 |
209 | ```ts
210 | class Boy {
211 | static handsome: boolean = true;
212 | constructor(public name: string) {}
213 | static isHandsome() {
214 | return this.handsome;
215 | }
216 | }
217 |
218 | let rain120 = new Boy('Rain120');
219 | console.log(Boy.handsome);
220 | console.log(Boy.isHandsome);
221 | console.log(rain120.handsome); // Property 'handsome' is a static member of type 'Boy'
222 | console.log(rain120.isHandsome); // Property 'isHandsome' is a static member of type 'Boy'
223 | ```
224 |
225 | [Playground](https://www.typescriptlang.org/play?#code/MYGwhgzhAEBCD2BPaBvAUNaEAuZsEthoALMAOwBMJ4BbAUwC5oAjeeEO86AXmmwCcArnQDcGaMHhkcQ4Nnj8AFAAdBzEIWhkw9JjPxkA5gEpUAX3E48m-BAAS5KrTqLT6TJn51sg-mT7EtgB0pJTU9GKYFhZoHNjQ-GAGAIwATAAMPFp0AO5wSIoA5ABKSWRp6YXGYpLS7HRBIPCGigiIIY7hdMZotdQcjc2tSEG2DmHOPX31gy2JKRkdE-RTUv0NTXNlFaP2nZNAA)
226 |
227 | ### 继承
228 |
229 | ```ts
230 | class Boy {
231 | handsome: boolean;
232 | name: string;
233 |
234 | constructor(name: string, handsome: boolean) {
235 | this.name = name;
236 | this.handsome = handsome;
237 | }
238 |
239 | isHandsome() {}
240 | }
241 |
242 | class Mine extends Boy {
243 | isHandsome() {
244 | return this.handsome;
245 | }
246 | }
247 |
248 | const mine = new Mine('Rain120', true);
249 | console.log(mine)
250 | ```
251 |
252 | [Playground](https://www.typescriptlang.org/play?#code/MYGwhgzhAEBCD2BPaBvAUNaALMA7AJhPALYCmAXNAEbzwil4DcG0uYZlEALgE4CWuAObNMLYPFzceAV2Bd4PABRsO0KQMEAabHkIkK1WvTwBKVC0xcsfCADoVpaAF5W7UiMzQrN2zgJEyZx1-fQ8AXxY0AEgbAAldANJFMxQIiLRQSBgAWQFHUgAPLlJ-OCRzTDiE-WSKzx5SLmkeXC9rOz89MnC0dPFJLmhiPKDcUgB3aFyxxQByACUwAQBGACYABlntXmlSE2Z+onpbEHhBRWGxkyA)
253 |
254 | ### 多态
255 |
256 | ```ts
257 | export function trace(cities: any, prop?: string, enterBreakPoint?: boolean): void;
258 |
259 | export function trace(cities: any, enterBreakPoint?: boolean): void;
260 |
261 | export function trace(enterBreakPoint?: boolean): void;
262 |
263 | export function trace(...args: any[]): void {
264 | }
265 | ```
266 |
267 | [Playground](https://www.typescriptlang.org/play?#code/KYDwDg9gTgLgBAMwK4DsDGMCWEVxlAQzWAAo1MtgBnALjgJQE8AaOMKCMAfjqv0xQBzVsBQxgUAEJRgBANYAFCAJg84AIwgQANrJQBKOgDdlAEwDcAKEuhIsRKgzZc+IqXKVa9JiLETpsorKYmqaOnqGcCaYFta20PDI6Fg4eITEJKLiUjLySiqhWroMkdGxNuAJDsnOaW4kAHRNBFCCXgyMANoAuqVmcADelgC+QA)
268 |
269 | ### 抽象类
270 |
271 | ```ts
272 | abstract class Boy {
273 | handsome: boolean;
274 | name: string;
275 |
276 | constructor(name: string, handsome: boolean) {
277 | this.name = name;
278 | this.handsome = handsome;
279 | }
280 |
281 | abstract isHandsome(): boolean;
282 | }
283 |
284 | class Mine extends Boy {
285 | isHandsome() {
286 | return this.handsome;
287 | }
288 | }
289 |
290 | const mine = new Mine('Rain120', true);
291 | console.log(mine);
292 | ```
293 |
294 | [Playground](https://www.typescriptlang.org/play?#code/IYIwzgLgTsDGEAJYBthjAgQgewJ4IG8AoBBAC2ADsATMbAWwFMAuBEbbZRqgbhIUrAmrSFACWlAOZ9S-WNkqiArvGxQAFIOEJREyQBpyVWgxZsOXKgEpC-UhDJiwAOi2MEAXgFDGM0ggcnZwoaOiZPI1DTPwBffn5QUThEJwAJYzDGdStWdk5uSj44ohQ0DABZCXdGAA8IRlCsPFtSNIzTbJb-KEYIJShKAMcXEJMmWKJi+UVEeiqIykYAdwRKxfUAcgAlYAkARgAmAAYNw2glRis+abouZ2RsSXU5xaugA)
295 |
296 | ### 把类当接口使用
297 |
298 | ```ts
299 | class Boy {
300 | handsome: boolean = true;
301 | }
302 |
303 | class Girl {
304 | beatiful: boolean = true;
305 | }
306 |
307 | enum Gender {
308 | 'MALE',
309 | 'FEMALE'
310 | }
311 |
312 | interface Person extends Boy, Girl {
313 | gender: Gender;
314 | }
315 | ```
316 |
317 | [Playground](https://www.typescriptlang.org/play?#code/MYGwhgzhAEBCD2BPaBvAUNaALMA7AJhPALYCmAXNAEbzwil7QC80ALgE4CupA3GgL5o0oSDADiAS3YhUGag1YSAZpxCUadBrmZsuvAUNK5OxaGKP5S7WZgDkAWQCCAGQCitgDRzbAMVdO3WwM0CVxWKyUwYFJoAAUrIm1SAA9wghgERA8zKRl0TABzCytKcwIrPn4gA)
318 |
319 | ## 快来耍耍啊
320 |
321 | ### 🌰🌰
322 |
323 |
324 |
325 | ```
326 | // template
327 | ```
328 |
329 | ### 游乐场
330 |
331 |
332 |
333 |
336 |
337 | ### 参考答案
338 |
339 | ```ts
340 | // answer
341 | ```
342 |
343 | ## 参考资料
344 |
345 | [handbook - classes](https://www.typescriptlang.org/docs/handbook/classes.html)
346 |
347 | [深入理解 TypeScript - 类](https://jkchao.github.io/typescript-book-chinese/faqs/class.html)
348 |
349 | [ECMAScript 6入门 - Class基本语法](https://es6.ruanyifeng.com/#docs/class)
350 |
351 | [类 (计算机科学)](https://zh.wikipedia.org/zh-cn/%E7%B1%BB_(%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6))
352 |
--------------------------------------------------------------------------------
/docs/zh/compile-config/README.md:
--------------------------------------------------------------------------------
1 | ## 配置
2 |
3 | - 手动 创建一个 `tsconfig.json`文件
4 | - 使用`tsc`命令
5 | - `npx tsc --init`
6 | - `npm i -g typescript` `tsc --init`
7 |
8 | `config` 文件解释
9 |
10 | ```json
11 | {
12 | "extends": "extends config files path", // 从另一个配置文件里继承配置
13 | "compileOnSave": true, // IDE在保存文件的时候根据tsconfig.json重新生成文件。
14 | "compilerOptions": {
15 | /* 基本选项 */
16 | "target": "es5", // 指定 ECMAScript 目标版本: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'
17 | "module": "commonjs", // 指定使用模块: 'commonjs', 'amd', 'system', 'umd' or 'es2015'
18 | "lib": [], // 指定要包含在编译中的库文件
19 | "allowJs": true, // 允许编译 javascript 文件
20 | "checkJs": true, // 报告 javascript 文件中的错误
21 | "jsx": "preserve", // 指定 jsx 代码的生成: 'preserve', 'react-native', or 'react'
22 | "declaration": true, // 生成相应的 '.d.ts' 文件
23 | "sourceMap": true, // 生成相应的 '.map' 文件
24 | "outFile": "./", // 将输出文件合并为一个文件
25 | "outDir": "./", // 指定输出目录
26 | "rootDir": "./", // 用来控制输出目录结构 --outDir.
27 | "removeComments": true, // 删除编译后的所有的注释
28 | "noEmit": true, // 不生成输出文件
29 | "importHelpers": true, // 从 tslib 导入辅助工具函数
30 | "isolatedModules": true, // 将每个文件做为单独的模块 (与 'ts.transpileModule' 类似).
31 |
32 | /* 严格的类型检查选项 */
33 | "strict": true, // 启用所有严格类型检查选项
34 | "noImplicitAny": true, // 在表达式和声明上有隐含的 any类型时报错
35 | "strictNullChecks": true, // 启用严格的 null 检查
36 | "noImplicitThis": true, // 当 this 表达式值为 any 类型的时候, 生成一个错误
37 | "alwaysStrict": true, // 以严格模式检查每个模块, 并在每个文件里加入 'use strict'
38 |
39 | /* 额外的检查 */
40 | "noUnusedLocals": true, // 有未使用的变量时, 抛出错误
41 | "noUnusedParameters": true, // 有未使用的参数时, 抛出错误
42 | "noImplicitReturns": true, // 并不是所有函数里的代码都有返回值时, 抛出错误
43 | "noFallthroughCasesInSwitch": true, // 报告 switch 语句的 fallthrough 错误。(即, 不允许 switch 的 case 语句贯穿)
44 |
45 | /* 模块解析选项 */
46 | "moduleResolution": "node", // 选择模块解析策略: 'node' (Node.js) or 'classic' (TypeScript pre-1.6)
47 | "baseUrl": "./", // 用于解析非相对模块名称的基目录
48 | "paths": {}, // 模块名到基于 baseUrl 的路径映射的列表
49 | "rootDirs": [], // 根文件夹列表, 其组合内容表示项目运行时的结构内容
50 | "typeRoots": [], // 包含类型声明的文件列表
51 | "types": [], // 需要包含的类型声明文件名列表
52 | "allowSyntheticDefaultImports": true, // 允许从没有设置默认导出的模块中默认导入。
53 |
54 | /* Source Map Options */
55 | "sourceRoot": "./", // 指定调试器应该找到 TypeScript 文件而不是源文件的位置
56 | "mapRoot": "./", // 指定调试器应该找到映射文件而不是生成文件的位置
57 | "inlineSourceMap": true, // 生成单个 soucemaps 文件, 而不是将 sourcemaps 生成不同的文件
58 | "inlineSources": true, // 将代码与 sourcemaps 生成到一个文件中, 要求同时设置了 --inlineSourceMap 或 --sourceMap 属性
59 |
60 | /* 其他选项 */
61 | "experimentalDecorators": true, // 启用装饰器
62 | "emitDecoratorMetadata": true // 为装饰器提供元数据的支持
63 | },
64 | "files": [], // 指定一个包含相对或绝对文件路径的列表
65 | "include": [], // 指定文件包含列表 (glob匹配模式)
66 | "exclude": [], // 指定文件过滤列表 (glob匹配模式)
67 | }
68 | ```
69 |
70 | [官网文档 - tsconfig.json](http://www.tslang.cn/docs/handbook/tsconfig-json.html)
71 |
72 | [tsconfig schema](http://json.schemastore.org/tsconfig)
73 |
74 | ::: tip
75 | 如果一个 `glob` 模式里的某部分只包含 `* 或 .*`, 那么仅有支持的文件扩展名类型被包含在内(比如默认 `.ts`, `.tsx`, 和 `.d.ts`, 如果 `allowJs: true` 还包含 `.js` 和`.jsx`)。
76 |
77 | 支持的 `glob` 通配符有:
78 |
79 | - **\*** 匹配0或多个字符(不包括目录分隔符)
80 |
81 | - **?** 匹配一个任意字符(不包括目录分隔符)
82 |
83 | - **\*\*/** 递归匹配任意子目录
84 |
85 | :::
86 |
87 | ## 编译选项
88 |
89 | 运行`tsc`即可将`ts`编辑成`js`文件, 运行`tsc -w` 在监视模式下运行编译器。
90 |
91 | `--watch / -w`: 在监视模式下运行编译器。会监视输出文件, 在它们改变时重新编译。监视文件和目录的具体实现可以通过环境变量进行配置。详情请看[配置 Watch](http://www.tslang.cn/docs/handbook/configuring-watch.html)。
92 |
93 | 编译会通过配置文件`tsconfig.json`中`files`, `include`, `exclude`来读取, 筛选文件。
94 |
95 | **Note:** 可以通过`globs`来匹配文件, `eg:` `lib/**/*`
96 |
97 | [编译选项](http://www.tslang.cn/docs/handbook/compiler-options.html)
98 |
99 | ## 配置详解
100 |
101 | - [references](./references/README.md)
102 |
103 | - [tsconfig-module-target](./tsconfig-module-target/README.md)
104 |
105 | - [TypeScript 文件包含相关配置](./file-inclusion/README.md)
106 |
107 | ## 参考资料
108 |
109 | [深入理解 TypeScript](https://jkchao.github.io/typescript-book-chinese/)
110 |
111 | [Typescritp tsconfig](https://www.typescriptlang.org/tsconfig)
112 |
--------------------------------------------------------------------------------
/docs/zh/compile-config/file-inclusion/README.md:
--------------------------------------------------------------------------------
1 | ## 定义
2 |
3 | 这些设置用于确保 `TypeScript` 处理正确的文件。
4 |
5 | ## 关键字
6 |
7 | ### extends
8 |
9 | 默认值: `false`
10 |
11 | `extends` 的值是一个字符串,它包含要继承的另一个配置文件的路径。路径可以使用 `Node.js` 样式解析。
12 |
13 | 首先加载基本文件中的配置,然后由 **继承的配置文件** 中的配置覆盖。**在配置文件中找到的所有相对路径都将相对于它们最初所在的配置文件进行解析。**
14 |
15 | 值得注意的是,从 **继承的配置文件** 中 [包含(include)](#include) 和 [排除(exclude)](#exclude) 的文件会覆盖从 **基本配置文件** 中 [包含(include)](#include) 和 [排除(exclude)](#exclude) 的文件,并且配置文件之间不允许循环。
16 |
17 | 目前,唯一被排除在继承之外的顶级属性是 [references](#references)。
18 |
19 | **Note👇👇👇**
20 |
21 | - 继承的配置文件: `tsconfig.json`
22 |
23 | - 基本配置文件: `tsconfig.base.json`
24 |
25 | `tsconfig.base.json`
26 | ```json
27 | {
28 | "compilerOptions": {
29 | "noImplicitAny": true,
30 | "strictNullChecks": true
31 | }
32 | }
33 | ```
34 |
35 | `tsconfig.json`
36 | ```json
37 | {
38 | "extends": "./tsconfig.base"
39 | }
40 | ```
41 |
42 | 在配置文件中找到的具有相对路径的属性(没有从继承中排除)将相对于它们的起始配置文件进行解析。
43 |
44 | ### exclude
45 |
46 | 默认值: `["node_modules", "bower_components", "jspm_packages"]`, 如果指定了一个, 则加上 `outDir` 的值。
47 |
48 | 它是用来指定解析 `include` 时应跳过的文件名或模式数组, 也就是文件过滤列表 (`glob` 匹配模式)。
49 |
50 | ```json
51 | {
52 | "exclude": ["node_modules"]
53 | }
54 | ```
55 |
56 | ### include
57 |
58 | 默认值: 除非被指定了文件, 否则就是 `["**/*"]`。
59 |
60 | 指定要包含在程序中的文件名或模式的数组。这些文件名是相对于包含`tsconfig.json` 的目录解析的文件。
61 |
62 | ```json
63 | {
64 | "include": ["src/**/*", "tests/**/*"]
65 | }
66 | ```
67 |
68 | 它将会包含
69 |
70 | ```sh
71 | .
72 | ├── scripts ⨯
73 | │ ├── lint.ts ⨯
74 | │ ├── update_deps.ts ⨯
75 | │ └── utils.ts ⨯
76 | ├── src ✓
77 | │ ├── client ✓
78 | │ │ ├── index.ts ✓
79 | │ │ └── utils.ts ✓
80 | │ ├── server ✓
81 | │ │ └── index.ts ✓
82 | ├── tests ✓
83 | │ ├── app.test.ts ✓
84 | │ ├── utils.ts ✓
85 | │ └── tests.d.ts ✓
86 | ├── package.json
87 | ├── tsconfig.json
88 | └── yarn.lock
89 | ```
90 |
91 | ::: tip
92 | `include` 和 `exclude`支持通配符来生成 `glob`模式, 如下 👇👇👇:
93 |
94 | - **\*** 匹配 0 或多个字符(不包括目录分隔符)
95 |
96 | - **?** 匹配一个任意字符(不包括目录分隔符)
97 |
98 | - **\*\*/** 递归匹配任意子目录
99 |
100 | 如果一个 `glob` 模式里的某部分只包含 `* 或 .*`, 那么仅有支持的文件扩展名类型被包含在内(比如默认 `.ts`, `.tsx`, 和 `.d.ts`, 如果 `allowJs: true` 还包含 `.js` 和`.jsx`)。
101 | :::
102 |
103 | ### files
104 |
105 | 默认值: `false`
106 |
107 | 指定程序中包含的文件的允许列表。如果无法找到任何文件,就会发生错误。
108 |
109 | ```json
110 | {
111 | "files": ["main.ts", "supplemental.ts"]
112 | }
113 | ```
114 |
115 | **Note:** 当您只有少量文件且不需要使用 `glob` 来引用许多文件时,这很有用。如果需要,那么使用[include](#include)。
116 |
117 | ### references
118 |
119 | 默认值: `false`
120 |
121 | 项目引用是一种将你的 `TypeScript` 程序结构成更小块的方法。使用`Project References` 可以极大地改进构建和编辑器的交互时间, 强制组件之间的逻辑分离, 并以新的和改进的方式组织代码。
122 |
123 | ```json
124 | {
125 | "references": [
126 | // ... path
127 | "some/path/which/you/want/to/set/it",
128 | ]
129 | }
130 | ```
131 |
132 | 你可以在 **官方手册** 中的[项目参考(Project References)](https://www.typescriptlang.org/docs/handbook/project-references.html)资料部分阅读更多关于参考资料如何工作的内容, 或者参考我另一篇笔记获取更多有关于 [Project References](../references/README.md) 的信息。
133 |
134 | ### typeAcquisition
135 |
136 | 默认是: `false`
137 |
138 | 当你的编辑器中有一个 `JavaScript` 项目时, `TypeScript` 会使用`@types` 定义的 `DefinitelyTyped` 集合自动为你的节点模块提供类型。这称为自动类型获取, 您可以使用配置中的 `typeAcquisition` 对象对其进行自定义。换句话来说就是设置自动引入库类型定义文件 `.d.ts` 相关。
139 |
140 | #### 语法
141 |
142 | ```json
143 | {
144 | // ...
145 | "typeAcquisition": {
146 | // 是否开启自动引入库类型定义文件 .d.ts,默认为 false
147 | "enable": false,
148 | // 允许自动引入的库名,如:[ "jquery", "lodash" ]
149 | "include": ["jest"],
150 | // 排除的库名。
151 | "exclude": ["jquery"],
152 | }
153 | }
154 |
155 | ```
156 |
157 | #### 使用
158 |
159 | 如果您想禁用或自定义此特性, 请创建 `jsconfig.json` 在项目的根目录中
160 |
161 | ```json
162 | {
163 | "typeAcquisition": {
164 | "enable": false
165 | }
166 | }
167 | ```
168 |
169 | 如果你有一个特定的模块, 应该包括(但不在 `node_modules` 中)
170 |
171 | ```json
172 | {
173 | "typeAcquisition": {
174 | "include": ["jest"]
175 | }
176 | }
177 | ```
178 |
179 | 如果不应该自动获取某个模块, 例如, 如果该库在您的 `node_modules` 中可用, 但您的团队已经同意不使用它
180 |
181 | ```json
182 | {
183 | "typeAcquisition": {
184 | "exclude": ["jquery"]
185 | }
186 | }
187 | ```
188 |
189 | 在`TypeScript 4.1`中, 还添加了禁用文件名触发类型获取的特殊大小写的功能。
190 |
191 | ```json
192 | {
193 | "typeAcquisition": {
194 | "disableFilenameBasedTypeAcquisition": true
195 | }
196 | }
197 | ```
198 |
199 | 这意味着在你的项目中有一个像 `jquery.js` 这样的文件不会自动从`DefinitelyTyped` 下载 `JQuery` 的类型。
200 |
201 | ## 快来耍耍啊
202 |
203 | ### 🌰🌰
204 |
205 |
206 |
207 | ```
208 |
209 | // template
210 |
211 | ```
212 |
213 | ### 游乐场
214 |
215 |
216 |
217 |
220 |
221 | ### 参考答案
222 |
223 | ```ts
224 | // answer
225 | ```
226 |
227 | ## 参考资料
228 |
229 | [typescript lang: File Inclusion](https://www.typescriptlang.org/tsconfig#Project_Files_0)
230 |
--------------------------------------------------------------------------------
/docs/zh/compile-config/module-resolver/README.md:
--------------------------------------------------------------------------------
1 | ## 定义
2 |
3 | 这些设置用于`TypeScript` 的模块解析。
4 |
5 | ## 关键字
6 |
7 | ### baseUrl
8 |
9 | 用于解析非相对模块名称的基目录。可以定义一个可以进行绝对文件解析的根文件夹。
10 |
11 | ```json
12 | {
13 | "compilerOptions": {
14 | "baseUrl": ".",
15 | }
16 | }
17 | ```
18 |
19 | ### paths
20 |
21 | 根据 `baseUrl` 配置来告知 `TypeScript` 应如何解析 `require` 或 `import` 中的导入。
22 |
23 | ```json
24 | {
25 | "compilerOptions": {
26 | "baseUrl": ".",
27 | },
28 | "paths": {
29 | "src": [
30 | "./src/**"
31 | ]
32 | }
33 | }
34 | ```
35 |
36 | ### rootDirs
37 |
38 | 使用 `rootDirs`,可以在构建时让编译器将这个路径列表中的路径的内容都放到一个文件夹中。
39 |
40 | ```json
41 | {
42 | "compilerOptions": {
43 | "rootDirs": [
44 | "src/home",
45 | "src/profile",
46 | ],
47 | }
48 | ```
49 |
50 | ### typeRoots
51 |
52 | 用来指定默认的类型声明文件查找路径,默认为 `node_modules/@types`, 指定 `typeRoots`后,`TypeScript` 编译器会从指定的路径去引入声明文件,而不是 `node_modules/@types`, 比如以下配置会从 `typings`路径下去搜索声明:
53 |
54 | ```json
55 | {
56 | "compilerOptions": {
57 | "typeRoots": ["./typings"]
58 | }
59 | }
60 | ```
61 |
62 | ### types
63 |
64 | `TypeScript` 编译器会默认引入 `typeRoots` 下所有的声明文件,但是有时候我们并不希望全局引入所有定义,而是仅引入部分模块。这种情景下可以通过 `types` 指定模块名只引入我们想要的模块,比如以下只会引入 `jquery` 的声明文件:
65 |
66 | ```json
67 | {
68 | "compilerOptions": {
69 | "types": ["jquery"]
70 | }
71 | }
72 | ```
73 |
74 | ## 快来耍耍啊
75 |
76 | ### 🌰🌰
77 |
78 |
79 |
80 | ```
81 | // template
82 | ```
83 |
84 | ### 游乐场
85 |
86 |
87 |
88 |
91 |
92 | ### 参考答案
93 |
94 | ```ts
95 | // answer
96 | ```
97 |
98 | ## 参考资料
99 |
100 |
101 |
--------------------------------------------------------------------------------
/docs/zh/compile-config/references/README.md:
--------------------------------------------------------------------------------
1 | ## 定义
2 |
3 | `reference (引用)` 是 `TypeScript 3.0`的新特性,它支持将项目的各个部分定义为单独的`TypeScript`模块, 分割成更小的组成部分。除此之外,这允许以不同的方式配置这些模块,分别构建它们等等。
4 |
5 | ## 什么是项目引用
6 |
7 | 每个引用的`path`属性都可以指向包含 `tsconfig.json` 文件的目录,或者配置文件本身(可以有任何名称)。当你引用一个项目时:
8 |
9 | - **从被引用的项目中导入模块将会加载它的输出声明文件`(.d.ts)`**
10 | - 如果引用的项目生成`outFile`,则在此项目中将显示输出文件`.d.ts`文件的声明
11 | - 如果需要,构建模式将自动构建引用的项目
12 |
13 | #### Note
14 |
15 | 引用的工程必须启用新的`composite`设置。 这个选项用于帮助TypeScript快速确定引用工程的输出文件位置。 若启用`composite`标记则会发生如下变动:
16 |
17 | - 对于`rootDir`设置,如果没有被显式指定,默认为包含`tsconfig`文件的目录
18 | - 所有的实现文件必须匹配到某个`include`模式或在`files`数组里列出。如果违反了这个限制,`tsc`会提示你哪些文件未指定。
19 | - 必须开启`declaration`选项。
20 |
21 | ## 作用
22 |
23 | `reference` 属性作用是 **指定工程引用依赖**。通过分成多个项目,可以大大提高类型检查和编译的速度,减少使用编辑器时的内存使用,并改善对程序逻辑组的执行。
24 |
25 | ## 使用
26 |
27 | ```ts
28 | type Reference = string[] & {
29 | path: string;
30 | prepend?: Boolean;
31 | }
32 | ```
33 |
34 | `prepend`选项可以启用前置某个依赖的输出,前置工程会将工程的输出添加到当前工程的输出之前。它对`.js`文件和`.d.ts`文件都有效,`source map`文件也同样会正确地生成。
35 |
36 | ### tsconfig.json
37 |
38 | ```json
39 | {
40 | "references": [
41 | // ... path
42 | "some/path/which/you/want/to/set/it",
43 | ]
44 | }
45 | ```
46 |
47 | 或者这样使用
48 |
49 | ```json
50 | {
51 | "references": [{
52 | "path": "some/path/which/you/want/to/set/it",
53 | "prepend": true
54 | }]
55 | }
56 | ```
57 |
58 | ## 快来耍耍啊
59 |
60 | ### 🌰🌰
61 |
62 |
63 |
64 | ```
65 | // template
66 | ```
67 |
68 | ### 游乐场
69 |
70 |
71 |
72 |
75 |
76 | ### 参考答案
77 |
78 | ```ts
79 | // answer
80 | ```
81 |
82 | ## 参考资料
83 |
84 | [Typescript Handbook Reference](https://www.typescriptlang.org/docs/handbook/project-references.html)
85 |
86 | [How to use project references in TypeScript 3.0?](https://stackoverflow.com/questions/51631786/how-to-use-project-references-in-typescript-3-0)
87 |
88 | [What is a Project Reference?](https://www.typescriptlang.org/docs/handbook/project-references.html#what-is-a-project-reference)
--------------------------------------------------------------------------------
/docs/zh/compile-config/tsconfig-module-target/README.md:
--------------------------------------------------------------------------------
1 | ## 前置
2 |
3 | 下面的内容在 `Typescript` 中是一个很常见的配置。
4 |
5 | ```json
6 | {
7 | "compilerOptions": {
8 | "target": "es5",
9 | "module": "es6"
10 | }
11 | }
12 | ```
13 |
14 | 很多时候, 我们会混淆 `target` 和 `module`的意思, 所以这篇, 我们主要是来讲一下这两个的作用。
15 |
16 | > **ESNEXT** 表示[最新标准](https://github.com/tc39/proposals)的 `js` 版本
17 |
18 | ## Target
19 |
20 | **指定编译的 `ECMAScript` 目标版本** `(与代码的输出相关)`。 默认值: **"ES3"**
21 |
22 | ```ts
23 | [
24 | 'ES5',
25 | 'ES2015',
26 | 'ES2016',
27 | 'ES2017',
28 | 'ES2018',
29 | 'ES2019',
30 | 'ESNEXT'
31 | ]
32 | ```
33 |
34 | ## Module
35 |
36 | **指定生成哪个模块系统代码**。 默认值: 根据 `--target` 选项不同而不同, 即 `target === "ES6" ? "ES6" : "commonjs"`
37 |
38 | ► 只有 `"AMD"` 和 `"System"` 能和 `--outFile` 一起使用。
39 |
40 | ► `"ES6"` 和 `"ES2015"` 可使用在目标输出为 `"ES5"` 或更低的情况下
41 |
42 | ```ts
43 | [
44 | 'none',
45 | 'commonjs',
46 | 'amd',
47 | 'system',
48 | 'umd',
49 | 'es2015',
50 | 'ESNEXT'
51 | ]
52 | ```
53 |
54 | ## 如何理解
55 |
56 | - **`module` 决定于引入方式**
57 |
58 | - **`target` 决定于输出方式**
59 |
60 | 模块系统独立于语言实现。`ES6(ES2015)` 模块使用 `import / export` 语法, 由模块加载器来解释。
61 |
62 | `JavaScript` 本身可能面向 `ES5`, 并且仅使用 `ES5` 功能, 但是从理论上讲, 可以将模块加载器与以`ES2015` 模块语法运行的代码一起使用。尽管有可能, 但不一定要执行此操作。在 `ES5 JavaScript` 中使用 `CommonJS` 或 `AMD` 模块更为常见。
63 |
64 | **Note:** 在 `TypeScript 2.0` 之前甚至不允许这种组合。
65 |
66 | ## 快来耍耍啊
67 |
68 | ### 🌰🌰
69 |
70 |
71 |
72 | ```
73 | // template
74 | ```
75 |
76 | ### 游乐场
77 |
78 |
79 |
80 |
83 |
84 | ### 参考答案
85 |
86 | ```ts
87 | // answer
88 | ```
89 |
90 | ## 参考资料
91 |
92 | [Understanding "target" and "module" in tsconfig](https://stackoverflow.com/questions/41993811/understanding-target-and-module-in-tsconfig)
93 |
94 | [编译选项](https://www.tslang.cn/docs/handbook/compiler-options.html)
--------------------------------------------------------------------------------
/docs/zh/declaration/README.md:
--------------------------------------------------------------------------------
1 | ## 声明文件
2 |
3 | 当使用第三方库时, 我们需要引用它的声明文件, 才能获得对应的代码补全、接口提示等功能。
4 |
5 | :::warning
6 | 声明文件必需以 `.d.ts` 为后缀。
7 | :::
8 |
9 | ### 项目如何识别声明文件(识别顺序)
10 |
11 | 优先从 `tsconfig.json` 配置的 `includes`字段配置的路径查询,然后从项目中查到`*.d.ts`文件,最后到 `node_modules/@types`路径中找。
12 |
13 | ### 声明文件位置
14 |
15 | - 第三方安装的 `@types/xxx`,会在 `node_modules/@types` 路径下。
16 | :::tip 应用方式
17 | 所有的 `@types` 包都会 **在编译时** 应用,`typescript` 会从 `node_modules/@types`,以及依赖包的 `node_modules/@types` 中去匹配到相应的 **类型定义文件**。
18 |
19 | ```sh
20 | .
21 | ├── node_modules
22 | │ ├── @types
23 | │ ├── pkg
24 | │ ├── node_modules
25 | │ ├── @types
26 | ```
27 | :::
28 |
29 | - 自定义的,我一般会写在项目的根路径 `typings` 或者 `@types`。
30 |
31 | :::tip 应用方式
32 | 自定义的 **类型定义** 可以通过 `tsconfig.json` 的配置 `compilerOptions.typesRoot` 来设置匹配的类型文件,如下👇🏻👇🏻👇🏻
33 |
34 | ```json
35 | {
36 | "compilerOptions": {
37 | "typeRoots" : ["./typings"]
38 | }
39 | }
40 | ```
41 |
42 | **Note:** 只有在 `typeRoots` 中的包才会被包含,也就是不会再去查找`node_modules/@types` 路径下 **类型定义** 了。
43 |
44 | 除此之外,也可以通过`compilerOptions.typesRoot` 来设置匹配的类型文件。
45 |
46 | ```json
47 | {
48 | "compilerOptions": {
49 | "types" : ["node", "lodash"]
50 | }
51 | }
52 | ```
53 |
54 | **Note:** 这样将只会包含下面两个类型定义,**其它的** 则不会被包含进来。
55 |
56 | ```sh
57 | .
58 | ├── node_modules
59 | │ ├── @types
60 | │ ├── node
61 | │ ├── lodash
62 | ```
63 | 如果配置为 `"types": []` 则不会包含任何包。
64 | :::
65 |
66 | ## 使用
67 |
68 | ### 直接使用第三方声明文件
69 |
70 | 我们在大不多数的时候, 都可以通过 `npm` 安装 **社区或者第三方类库** 提供对应的声明模块即可。
71 |
72 | ```sh
73 | npm install --save-dev @types/pkg-name
74 |
75 | // or
76 |
77 | yarn add --save-dev @types/pkg-name
78 | ```
79 |
80 | ::: tip 更多声明模块
81 |
82 | - 搜索 🔍 [here](https://www.typescriptlang.org/dt/search/)
83 |
84 | - 发布声明文件 🖥 [here](http://definitelytyped.org/)
85 |
86 | - 查看 👁👁 [here](https://github.com/DefinitelyTyped/DefinitelyTyped)
87 |
88 |
89 | :::
90 |
91 | ### 自定义声明文件
92 |
93 | 当然, 社区不是万能的, 有时候, 有些声明文件需要我们自己自定义, 那我们将如何书写呢?👇👇👇
94 |
95 | 在不同的场景下, 声明文件的内容和使用方式会有所区别。
96 |
97 | #### 全局变量
98 |
99 | `declare global` 扩展全局变量
100 |
101 | ```ts
102 | // xxx.d.ts
103 | declare global {
104 | // ...
105 | }
106 | ```
107 |
108 | `declare (var | let | const)` 声明全局变量
109 |
110 | ```ts
111 | // JQuery.d.ts
112 | declare var JQuery: (selector: string) => any;
113 | declare let JQuery: (selector: string) => any;
114 | declare const JQuery: (selector: string) => any;
115 | ```
116 |
117 | `declare function` 声明全局方法, 在函数类型的声明语句中, 函数重载也是支持的
118 |
119 | ```ts
120 | // xxx.d.ts
121 | declare function moduleLib(options: Options): void;
122 | declare function moduleLib(callback: () => void): void;
123 | ```
124 |
125 | `declare class` 声明全局类
126 |
127 | ```ts
128 | // xxx.d.ts
129 | declare class Person {
130 | name: string;
131 | constructor(name: string);
132 | getName(): string;
133 | }
134 | ```
135 |
136 | `declare enum` 声明全局枚举类型
137 |
138 | ```ts
139 | // xxx.d.ts
140 | declare enum Days {
141 | Sun,
142 | Mon,
143 | Tue,
144 | Wed,
145 | Thu,
146 | Fri,
147 | Sat,
148 | }
149 | ```
150 |
151 | ::: warning
152 |
153 | `declare enum`, `declare class` , `declare enum` 语句**只能用来定义类型**, 不能用来定义具体的实现, 也不是具体的值。
154 |
155 | :::
156 |
157 | `interface` 和 `type` 声明全局类型, 如果你需要将一下类型定义暴露出来, 可以使用 `interface`或者 `type`。
158 |
159 | 为了**防止命名冲突**, 暴露在最外层的 `interface` 或 `type` 会作为全局类型作用于整个项目中, 我们应该尽可能的减少全局变量或全局类型的数量。
160 |
161 | ```ts
162 | // xxx.d.ts
163 | export interface Day {
164 | format: (value: Date) => string;
165 | }
166 |
167 | export type Time = Day | null;
168 | ```
169 |
170 | `declare namespace` 声明 (含有子属性的) 全局对象
171 |
172 | 随着 `ES6` 的广泛应用, 现在已经**不建议再使用** `ts` 中的 `namespace`, 而推荐使用 `ES6` 的模块化, 例如 `import foo from 'foo'`。
173 |
174 | ```ts
175 | // xxx.d.ts
176 | export type Method = 'GET' | 'POST' | 'DELETE' | 'OPTIONS';
177 |
178 | export interface Options {
179 | method: Method;
180 | [key: string]?: any;
181 | }
182 |
183 | declare namespace $ {
184 | const version: number | string;
185 | function ajax(url: string, options?: Options): void;
186 | // 嵌套命名空间
187 | namespace get {
188 | function getSomething(id: string): any;
189 | // etc...
190 | }
191 | }
192 | ```
193 |
194 | #### `ES6` 模块
195 |
196 | 符合 `ES6` 模块 `(module)` 导入导出规范
197 |
198 | `export` 导出变量
199 |
200 | ```ts
201 | // xxx.d.ts
202 | export const name: string;
203 | ```
204 |
205 | `export namespace` 导出 (含有子属性的) 对象
206 |
207 | ```ts
208 | // xxx.d.ts
209 | export declare namespace $ {
210 | const version: number | string;
211 | function ajax(url: string, options?: Options): void;
212 | // 嵌套命名空间
213 | namespace get {
214 | function getSomething(id: string): any;
215 | // etc...
216 | }
217 | }
218 | ```
219 |
220 | `export default ES6` 默认导出
221 |
222 | ```ts
223 | // xxx.d.ts
224 | export default function getRandomColor(): string;
225 | ```
226 |
227 | ::: warning
228 |
229 | 只有 `function`、`class` 和 `interface` 可以直接默认导出, 其他的变量需要先定义出来, 再默认导出
230 |
231 | :::
232 |
233 | `export = commonjs` 导出模块
234 |
235 | ```ts
236 | // xxx.d.ts
237 | // 整体导出
238 | module.exports = foo;
239 | // 单个导出
240 | exports.bar = bar;
241 | ```
242 |
243 | `export as namespace UMD` 库声明全局变量
244 |
245 | 一般使用 `export as namespace` 时, 都是先有了 npm 包的声明文件, 再基于它添加一条 `export as namespace` 语句, 即可将声明好的一个变量声明为全局变量。
246 |
247 | ```ts
248 | // xxx.d.ts
249 | export as namespace moment;
250 | declare namespace moment {
251 | export function valueOf(): number;
252 | }
253 | ```
254 |
255 | `declare module` 扩展模块
256 |
257 | ```ts
258 | // xxx.d.ts
259 | // 导入 moment
260 | declare module 'moment' {
261 | export function valueOf(): number;
262 | }
263 |
264 | // 导入 lodash
265 | declare module 'lodash' {
266 | export function isEmpty(params: any): boolean;
267 | }
268 |
269 | // 导入 png 图片
270 | declare module '*.png' {
271 | const value: string;
272 | export = value;
273 | }
274 | ```
275 |
276 | #### 声明合并
277 |
278 | - **函数** 合并(**重载**)
279 |
280 | ```ts
281 | function getFullName(x: function): string;
282 | function getFullName(x: string): string;
283 | function getFullName(x: string | function): string {
284 | if (typeof x === 'function') {
285 | return x();
286 | } else {
287 | return x;
288 | }
289 | }
290 | ```
291 |
292 | - **接口 & 类** 合并
293 |
294 | ```ts
295 | interface Profile {
296 | name: string;
297 | getAge(): number;
298 | }
299 |
300 | interface Profile {
301 | age: number | string;
302 | getAge(): string;
303 | }
304 |
305 | // =>
306 | interface Profile {
307 | // 属性必须唯一
308 | name: string;
309 | age: number | string;
310 | // 这里和函数合并保持一致, 因为函数可以重载
311 | getAge(): number;
312 | getAge(): string;
313 | }
314 | ```
315 |
316 | :::warning
317 |
318 | 接口合并的**属性的类型必须是唯一的**。
319 |
320 | :::
321 |
322 | #### 使用依赖
323 |
324 | 以下情况可以通过使用 **/// 三斜线指令** 来解决。
325 |
326 | - 依赖全局库
327 | - 依赖模块
328 | - 依赖`UMD`库
329 | - 全局库
330 | - 一个模块或`UMD`库
331 |
332 | 随着 `ES6` 的广泛应用, 现在已经不建议再使用 `ts` 中的三斜线指令来声明模块之间的依赖关系了。
333 |
334 | ```ts
335 | // xxx.d.ts
336 | ///
337 | ```
338 |
339 | ::: warning
340 |
341 | *不要*使用`/// 需要注意的是, 在 `TypeScript 1.5` 中, 命名法发生了变化。内部模块 `(Internal modules)` 现在是 _namespaces_。外部模块 `(External modules)` 现在只是简单的 _modules_。_内部模块_ 是没有引号的模块
413 |
414 | [更多信息可以到 Github issue#13774](https://github.com/Microsoft/TypeScript/issues/13774)
415 |
416 | ## 快来耍耍啊
417 |
418 | ### 🌰🌰
419 |
420 |
421 |
422 | ```
423 | // template
424 | ```
425 |
426 | ### 游乐场
427 |
428 |
429 |
430 |
433 |
434 | ### 参考答案
435 |
436 | ```ts
437 | // answer
438 | ```
439 |
440 | ## 参考资料
441 |
442 | [handbook: namespaces](https://www.typescriptlang.org/docs/handbook/namespaces.html)
443 |
444 | [handbook: Namespaces and Modules](https://www.typescriptlang.org/docs/handbook/namespaces-and-modules.html)
445 |
446 | [handbook: declaration-files](https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-d-ts.html)
447 |
448 | [How do I use namespaces with TypeScript external modules?](https://stackoverflow.com/questions/30357634/how-do-i-use-namespaces-with-typescript-external-modules)
449 |
450 | [Validators in a single file](https://www.typescriptlang.org/docs/handbook/namespaces.html#validators-in-a-single-file)
451 |
452 | [Module vs Namespace - Import vs Require Typescript](https://stackoverflow.com/questions/38582352/module-vs-namespace-import-vs-require-typescript)
453 |
454 | [Is typescript Namespace feature deprecated?](https://michelenasti.com/2019/01/23/is-typescript-namespace-feature-deprecated.html)
455 |
456 | [Module vs Namespace - Import vs Require Typescript](https://stackoverflow.com/questions/38582352/module-vs-namespace-import-vs-require-typescript)
457 |
458 | [如何在 TypeScript 外部模块中使用命名空间?](https://stackoverflow.com/questions/30357634/how-do-i-use-namespaces-with-typescript-external-modules)
459 |
460 | [声明文件](https://ts.xcatliu.com/basics/declaration-files.html)
461 |
--------------------------------------------------------------------------------
/docs/zh/decorators/README.md:
--------------------------------------------------------------------------------
1 | ## 定义
2 |
3 | **装饰器**是一种特殊类型的声明, 它能够被附加到[类声明](http://www.tslang.cn/docs/handbook/decorators.html#class-decorators), [方法](http://www.tslang.cn/docs/handbook/decorators.html#method-decorators), [访问符](http://www.tslang.cn/docs/handbook/decorators.html#accessor-decorators), [属性](http://www.tslang.cn/docs/handbook/decorators.html#property-decorators)或[参数](http://www.tslang.cn/docs/handbook/decorators.html#parameter-decorators)上。 装饰器使用 `@expression` 这种形式, `expression` 求值后必须为一个函数, 它会在运行时被调用, 被装饰的声明信息做为参数传入。
4 |
5 | 了解更多有关装饰器实现原理的知识 👉👉👉 [Javascript Decorator (装饰器) 实现原理及其使用](https://rain120.github.io/study-notes/#/notes/javascript/key-concept/decorator?id=javascript-decorator-装饰器-实现原理及其使用)
6 |
7 | ### 类型 & 优先级
8 |
9 | **优先级依次往下执行**
10 |
11 | 1. 参数装饰器 `(Parameter Decorators)`
12 |
13 | **参数装饰器**声明在一个参数声明之前(紧靠着参数声明)。 参数装饰器应用于类构造函数或方法声明。 参数装饰器不能用在声明文件`(.d.ts)`, 重载或其它外部上下文(比如 `declare`的类)里。
14 |
15 | 2. 方法装饰器 `(Method Decorators)`
16 |
17 | **方法装饰器**声明在一个方法的声明之前(紧靠着方法声明)。 它会被应用到方法的 *属性描述符*上, 可以用来监视, 修改或者替换方法定义。 方法装饰器不能用在声明文件`(.d.ts)`, 重载或者任何外部上下文(比如`declare`的类)中。
18 |
19 | 3. 访问器或属性装饰器 `(Accessor or Property Decorators)`
20 |
21 | **访问器装饰器**声明在一个访问器的声明之前(紧靠着访问器声明)。 访问器装饰器应用于访问器的 *属性描述符*并且可以用来监视, 修改或替换一个访问器的定义。 访问器装饰器不能用在声明文件中`(.d.ts)`, 或者任何外部上下文(比如 `declare` 的类)里。
22 |
23 | **属性装饰器**声明在一个属性声明之前(紧靠着属性声明)。 属性装饰器不能用在声明文件中`(.d.ts)`, 或者任何外部上下文(比如 `declare` 的类)里。
24 |
25 | 1. 类属性
26 | 2. 构造函数参数列表 `(使用类构造函数装饰器时)`
27 |
28 | **Note:** 访问器 `get` `set`
29 |
30 | 4. 类装饰器 `(Class Decorators)`
31 |
32 | **类装饰器** 在类声明之前被声明 (紧靠着类声明)。 类装饰器应用于类构造函数, 可以**用来监视, 修改或替换类定义**。 类装饰器不能用在声明文件中( `.d.ts`), 也不能用在任何外部上下文中(比如`declare`的类)。
33 |
34 | ## 使用
35 |
36 | 若要启用实验性的装饰器特性, 你必须在命令行或`tsconfig.json`里启用`experimentalDecorators`编译器选项:
37 |
38 | **命令行**:
39 |
40 | ```shell
41 | tsc --target ES5 --experimentalDecorators
42 | ```
43 |
44 | **tsconfig.json**:
45 |
46 | ```json
47 | {
48 | "compilerOptions": {
49 | "target": "ES5",
50 | "experimentalDecorators": true
51 | }
52 | }
53 | ```
54 |
55 | ### 装饰器组合
56 |
57 | 多个装饰器可以同时应用声明到一个 [类声明](http://www.tslang.cn/docs/handbook/decorators.html#class-decorators), [方法](http://www.tslang.cn/docs/handbook/decorators.html#method-decorators), [访问符](http://www.tslang.cn/docs/handbook/decorators.html#accessor-decorators), [属性](http://www.tslang.cn/docs/handbook/decorators.html#property-decorators)或[参数](http://www.tslang.cn/docs/handbook/decorators.html#parameter-decorators)上。
58 |
59 | ```ts
60 | // 一行写法
61 | @f @g isHandsome() {}
62 |
63 | // 多行写法 ----> 个人喜欢这种写法
64 | @f
65 | @g
66 | isHandsome() {}
67 | ```
68 |
69 | 当复合 **f** 和 **g** 时, [复合](https://zh.wikipedia.org/wiki/%E5%A4%8D%E5%90%88%E5%87%BD%E6%95%B0) `(把一个函数的输出作为另一个函数的输入)`的结果 $(f ∘ g)(x) = f(g(x))$。
70 |
71 | **Note:** 当在一个地方使用**多个装饰器**时
72 |
73 | - **由上至下**依次对装饰器表达式求值
74 | - 执行顺序是 **从下往上** 依次执行。
75 |
76 | ```ts
77 | function first() {
78 | console.log('first: evaluated');
79 | return (target, propertyKey: string, descriptor: PropertyDescriptor) => {
80 | console.log('first: called');
81 | };
82 | }
83 |
84 | function second() {
85 | console.log('second: evaluated');
86 | return (target, propertyKey: string, descriptor: PropertyDescriptor) => {
87 | console.log('second: called');
88 | };
89 | }
90 |
91 | class Example {
92 | @second
93 | @first
94 | method() {}
95 | }
96 |
97 | // 'second: evaluated'
98 | // 'first: evaluated'
99 | // 'first: called'
100 | // 'second: called'
101 | ```
102 |
103 | ### 参数装饰器
104 |
105 | 参数装饰器表达式会在运行时当作函数被调用, 传入下列 3 个参数:
106 |
107 | 1. 对于静态成员来说是类的构造函数, 对于实例成员是类的原型对象。
108 | 2. 成员的名字。
109 | 3. 参数在函数参数列表中的索引。
110 |
111 | ::: warning
112 | 注意: 参数装饰器只能用来监视一个方法的参数是否被传入。
113 | :::
114 |
115 | 参数装饰器的返回值会被忽略。
116 |
117 | ```ts
118 | function parameterDecorator(value: boolean) {
119 | return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
120 | console.log('parameterDecorator');
121 | };
122 | }
123 |
124 | class Boy {
125 | name: string;
126 | age: number;
127 | handsome: boolean;
128 |
129 | constructor(name, handsome) {
130 | this.name = name;
131 | this.handsome = handsome;
132 | }
133 |
134 | setAge(@parameterDecorator('parameterDecorator') age: number) {
135 | this.age = age;
136 | }
137 | }
138 | ```
139 |
140 | ### 方法装饰器
141 |
142 | 方法装饰器表达式会在运行时当作函数被调用, 传入下列 3 个参数:
143 |
144 | 1. 对于静态成员来说是类的构造函数, 对于实例成员是类的原型对象。
145 | 2. 成员的名字。
146 | 3. 成员的 **属性描述符**。
147 |
148 | ::: warning
149 | 如果代码输出目标版本小于`ES5`, *属性描述符*将会是`undefined`。
150 | :::
151 |
152 | 如果方法装饰器返回一个值, 它会被用作方法的*属性描述符*。
153 |
154 | ::: warning
155 | 如果代码输出目标版本小于`ES5`返回值会被忽略。
156 | :::
157 |
158 | ```ts
159 | function methodDecorator(value: boolean) {
160 | return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
161 | target[propertyKey] = value;
162 | };
163 | }
164 |
165 | class Boy {
166 | name: string;
167 | handsome: boolean;
168 |
169 | @propertyDecorator('属性装饰器', Boy)
170 | public age: number = 18;
171 |
172 | constructor(name, handsome) {
173 | this.name = name;
174 | this.handsome = handsome;
175 | }
176 |
177 | @methodDecorator(true)
178 | isHandsome() {
179 | return this.handsome;
180 | }
181 | }
182 | ```
183 |
184 | ### 访问器或属性装饰器
185 |
186 | #### 属性装饰器
187 |
188 | 属性装饰器表达式会在运行时当作函数被调用, 传入下列 `2` 个参数:
189 |
190 | 1. 对于静态成员来说是类的构造函数, 对于实例成员是类的原型对象。
191 | 2. 成员的名字。
192 |
193 | ::: warning
194 | **属性描述符** 不会做为参数传入属性装饰器, 这与`TypeScript`是如何初始化属性装饰器的有关。 因为目前没有办法在定义一个原型对象的成员时描述一个实例属性, 并且没办法监视或修改一个属性的初始化方法。返回值也会被忽略。因此, 属性描述符只能用来监视类中是否声明了某个名字的属性。
195 | :::
196 |
197 | ```ts
198 | function propertyDecorator(value: string, theClass) {
199 | console.log(value);
200 | return function(prototype, key) {
201 | console.log('AccessDecorator');
202 | };
203 | }
204 |
205 | class Boy {
206 | name: string;
207 | handsome: boolean;
208 |
209 | @propertyDecorator('属性装饰器', Boy)
210 | public age: number = 18;
211 |
212 | constructor(name, handsome) {
213 | this.name = name;
214 | this.handsome = handsome;
215 | }
216 |
217 | @AccessDecorator('访问器装饰器')
218 | get isHandsome() {
219 | return this.handsome;
220 | }
221 | }
222 | ```
223 |
224 | #### 访问器装饰器
225 |
226 | ::: warning
227 | `TypeScript`不允许同时装饰一个成员的`get` 和 `set` 访问器。取而代之的是, 一个成员的所有装饰的必须应用在文档顺序的第一个访问器上。这是因为, 在装饰器应用于一个**属性描述符**时, 它联合了 `get` 和 `set` 访问器, 而不是分开声明的。
228 | :::
229 |
230 | 访问器装饰器表达式会在运行时当作函数被调用, 传入下列 3 个参数:
231 |
232 | 1. 对于静态成员来说是类的构造函数, 对于实例成员是类的原型对象。
233 | 2. 成员的名字。
234 | 3. 成员的**属性描述符**。
235 |
236 | ::: warning
237 | 如果代码输出目标版本小于 `ES5`, **Property Descriptor** 将会是 `undefined`。
238 | :::
239 |
240 | 如果访问器装饰器返回一个值, 它会被用作方法的*属性描述符*。
241 |
242 | ::: warning
243 | 如果代码输出目标版本小于 `ES5` 返回值会被忽略。
244 | :::
245 |
246 | ```ts
247 | function AccessDecorator(value: string) {
248 | console.log(value);
249 | return function() {
250 | console.log('AccessDecorator');
251 | };
252 | }
253 |
254 | class Boy {
255 | name: string;
256 | handsome: boolean;
257 |
258 | constructor(name, handsome) {
259 | this.name = name;
260 | this.handsome = handsome;
261 | }
262 |
263 | @AccessDecorator('访问器装饰器')
264 | get isHandsome() {
265 | return this.handsome;
266 | }
267 | }
268 | ```
269 |
270 | ### 类装饰器
271 |
272 | 类装饰器表达式会在运行时当作函数被调用, **类的构造函数作为其唯一的参数**。
273 |
274 | 如果类装饰器返回一个值, 它会使用提供的构造函数来替换类的声明。
275 |
276 | ::: warning
277 | 如果你要返回一个新的构造函数, 你必须注意处理好原来的原型链。在运行时的装饰器调用逻辑中 **不会** 为你做这些。
278 | :::
279 |
280 | ```ts
281 | function sealed(constructor: Function) {
282 | Object.seal(constructor);
283 | Object.seal(constructor.prototype);
284 | }
285 |
286 | @sealed
287 | class Greeter {
288 | greeting: string;
289 | constructor(message: string) {
290 | this.greeting = message;
291 | }
292 | greet() {
293 | return 'Hello, ' + this.greeting;
294 | }
295 | }
296 | ```
297 |
298 | ## 快来耍耍啊
299 |
300 | ### 🌰🌰
301 |
302 |
303 |
304 | ```
305 | // template
306 | ```
307 |
308 | ### 游乐场
309 |
310 |
311 |
312 |
315 |
316 | ### 参考答案
317 |
318 | ```ts
319 | // answer
320 | ```
321 |
322 | ## 参考资料
323 |
324 | [handbook - decorators](https://www.typescriptlang.org/docs/handbook/decorators.html)
325 |
326 | [使用 TypeScript 装饰器装饰你的代码](https://codeburst.io/decorate-your-code-with-typescript-decorators-5be4a4ffecb4)
327 |
--------------------------------------------------------------------------------
/docs/zh/faqs/README.md:
--------------------------------------------------------------------------------
1 | ## FAQs 列表
2 |
3 | [interface 和 type 有什么异同点?](./interface-vs-type.md)
4 |
5 | ## 参考资料
6 |
7 |
8 |
--------------------------------------------------------------------------------
/docs/zh/faqs/interface-vs-type.md:
--------------------------------------------------------------------------------
1 | ## interface 和 type 有什么异同点?
2 |
3 | [interface-declarations](https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#71-interface-declarations)
4 |
5 | > An interface cannot declare a property with the same name as an inherited private or protected property.
6 |
7 | [type-aliases](https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#310-type-aliases)
8 |
9 | > An interface can have multiple merged declarations, but a type alias for an object type literal cannot
10 |
11 | ### 相同点
12 |
13 | - 描述一个对象或者函数
14 |
15 | ```typescript
16 | export interface IUser {
17 | id: string | number;
18 | name: string;
19 | age?: number;
20 | }
21 |
22 | export interface IGetUser {
23 | (id: string | number): IUser;
24 | }
25 |
26 | export type User = {
27 | name: string;
28 | age?: number;
29 | }
30 |
31 | export type GetUser = (id: string | number): User;
32 |
33 | ```
34 |
35 | - 允许类型拓展(`type`不能使用`extends`关键字)
36 |
37 | ```typescript
38 | interface FE extends IUser {
39 | type: string;
40 | }
41 |
42 | type FE = { type: string; } & User;
43 |
44 | ```
45 |
46 | ### 不同点
47 |
48 | - `type` 可以声明基本类型别名, 联合类型, 元组等类型
49 |
50 | - `interface` 能够声明合并
51 |
52 | ```typescript
53 | interface IUser {
54 | id: string | number;
55 | }
56 |
57 | interface IUser {
58 | name: string;
59 | age?: number;
60 | }
61 |
62 | // =>
63 | interface IUser {
64 | id: string | number;
65 | name: string;
66 | age?: number;
67 | }
68 | ```
69 |
70 | ## 参考资料
71 |
72 | [handbook - type-inference](https://www.typescriptlang.org/docs/handbook/type-inference.html)
73 |
74 | [interfaces](https://basarat.gitbook.io/typescript/type-system/interfaces)
75 |
76 | [typescript-interfaces-vs-types](https://stackoverflow.com/questions/37233735/typescript-interfaces-vs-types)
77 |
78 | [handbook - differences-between-type-aliases-and-interfaces](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#differences-between-type-aliases-and-interfaces)
79 |
--------------------------------------------------------------------------------
/docs/zh/function/README.md:
--------------------------------------------------------------------------------
1 | ## 函数
2 |
3 | :::theorem 函数
4 | 函数是 `JavaScript` 中的基本组件之一。 一个函数是 `JavaScript` 过程 ---- 一组执行任务或计算值的语句。要使用一个函数, 你必须将其定义在你希望调用它的作用域内。
5 | :::
6 |
7 | ### TypeScript VS JavaScript
8 |
9 | | TypeScript | JavaScript |
10 | | -------------- | ------------------------------------------------------------ |
11 | | 含有类型 | 无类型 |
12 | | 箭头函数 | 箭头函数 `(ES2015)` |
13 | | 函数类型 | 无函数类型 |
14 | | 必填和可选参数 | 所有参数都是可选的, 如果传入了参数, 该参数, 后面的参数都是可选的 |
15 | | 默认参数 | 默认参数 |
16 | | 剩余参数 | 剩余参数 |
17 | | 函数重载 | 无函数重载 |
18 |
19 | ### 函数的组成
20 |
21 | - 函数的名称
22 |
23 | - 函数参数列表, 包围在括号中并由逗号分隔。
24 |
25 | - 定义函数的 `JavaScript` 语句, 用大括号 `{}` 括起来
26 |
27 | - 函数的返回值
28 |
29 | ## 声明(定义)函数
30 |
31 | `JavaScript` 中声明函数有👇👇👇方式, 在 `Typescript` 中也是一样的。
32 |
33 | ### 函数声明 (Function Declaration)
34 |
35 | ```ts
36 | function getFullName(name: string): string {
37 | return `Rainy ${name}`;
38 | }
39 | ```
40 |
41 | ### 函数表达式 (Function Expression)
42 |
43 | 函数也可以由函数表达式创建, 这样的函数可以是 **匿名的**。
44 |
45 | ```ts
46 | const getFullName: (name: string) => string = function(name: string): string {
47 | return `Rainy ${name}`;
48 | }
49 | ```
50 | 当然你也可以使用箭头函数
51 |
52 | ```ts
53 | const getFullName: (name: string) => string = (name: string): string => {
54 | return `Rainy ${name}`;
55 | }
56 | ```
57 |
58 | **Note:**
59 |
60 | - 在 `TypeScript` 的类型定义中, `=>` 用来表示函数的定义的 **输出类型** 。
61 | - `ES6` 允许使用 **箭头** (`=>`) 定义函数, 更多详见 [ES6 箭头函数](http://es6.ruanyifeng.com/#docs/function#%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0)
62 |
63 | ## 声明函数定义方式
64 |
65 | ### 匿名定义
66 |
67 | ```ts {1}
68 | const getFullName: (name: string) => string
69 | = function(name: string): string {
70 | return `Rainy ${name}`;
71 | }
72 | ```
73 |
74 |
75 | 如果你会使用 `type`, `interface` 了, 你也可以这样
76 |
77 | ### type 定义
78 |
79 | ```ts {1}
80 | type GetFullName = (name: string) => string;
81 | ```
82 |
83 | 还可以这样
84 |
85 | ### 接口 (Interface) 定义
86 |
87 | ```ts {2}
88 | interface GetFullName {
89 | (name: string) => string;
90 | }
91 | ```
92 |
93 | ## 函数参数
94 |
95 | ### 可选参数
96 |
97 | `JavaScript` 每个参数都是可选的, 可传可不传。 没传参的时候, 它的值就是 `undefined` , `TypeScript` 里的每个函数参数都是必须的, 它可以通过使用 `?`实现可选参数的功能。
98 |
99 | ```ts
100 | function getInfo(
101 | name: string,
102 | gender: number | string,
103 | age?: number | string
104 | ): {
105 | return `I'm ${name}${age ? `${, I'm ${age}}` : ''}, I'm a ${gender}.`
106 | }
107 | ```
108 |
109 | **Note:** 可选参数 **必须要** 放在 必选参数 的 **后面**, 不然会导致编译错误。
110 |
111 | ### 默认参数
112 |
113 | 在 `TypeScript` 里, 我们也可以为参数提供一个默认值当用户没有传递这个参数或传递的值是`undefined`时。 它们叫做有默认初始化值的参数。
114 |
115 | ```ts
116 | function getInfo(
117 | name: string,
118 | gender: number | string = 'boy',
119 | age?: number | string
120 | ): {
121 | return `I'm ${name}${age ? `${, I'm ${age}}` : ''}, I'm a ${gender}.`
122 | }
123 | ```
124 |
125 | ### 剩余参数
126 |
127 | 剩余参数会被当做个数不限的可选参数。 可以一个都没有, 同样也可以有任意个。 编译器创建参数数组, 可以通过扩展运算符 `(spread)` 来设置参数名。
128 |
129 | [扩展运算符(spread)](https://es6.ruanyifeng.com/?search=扩展&x=8&y=10#docs/array#扩展运算符) 是 三个 (`...`), 它好比 `rest` 参数的逆运算, 将一个数组转为用逗号分隔的参数序列。
130 |
131 | ```ts
132 | function buildName(firstName: string, ...restOfName: string[]) {
133 | return firstName + " " + restOfName.join(" ");
134 | }
135 |
136 | let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
137 | ```
138 |
139 | ## 函数重载
140 |
141 | [函数重载](https://zh.wikipedia.org/wiki/函数重载) 是定义了多个相同名字的方法, 而输入输出类型或个数不同的子程序的一项特性。
142 |
143 | 可惜 `JavaScript` 不支持函数重载, 但是 `Typescript` 支持。
144 |
145 | ```ts
146 | function add(a: number, b: number): number;
147 | function add(a: string, b: string): string;
148 | function add(a: string, b: number): string;
149 | function add(a: number, b: string): string;
150 | function add(a: Combinable, b: Combinable) {
151 | if (typeof a === "string" || typeof b === "string") {
152 | return a.toString() + b.toString();
153 | }
154 | return a + b;
155 | }
156 | ```
157 |
158 | **Note:** `TypeScript` 会优先从最前面的函数定义开始匹配, 所以多个函数定义如果有包含关系, 需要优先把精确的定义写在前面。
159 |
160 | ## 快来耍耍啊
161 |
162 | ### 🌰🌰
163 |
164 |
165 |
166 | ```
167 | // template
168 | ```
169 |
170 | ### 游乐场
171 |
172 |
173 |
174 |
177 |
178 | ### 参考答案
179 |
180 | ```ts
181 | // answer
182 | ```
183 |
184 | ## 参考资料
185 |
186 | [handbook - functions](https://www.typescriptlang.org/docs/handbook/functions.html)
187 |
188 | [functions](https://basarat.gitbook.io/typescript/type-system/functions)
189 |
190 | [MDN - Functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions)
191 |
--------------------------------------------------------------------------------
/docs/zh/generics/README.md:
--------------------------------------------------------------------------------
1 | ## 定义
2 |
3 | **泛型**就是指定一个表示类型的变量, 用它来代替某个实际的类型用于编程, 而后再通过实际运行或推导的类型来对其进行替换, 以达到一段使用泛型程序可以实际适应不同类型的目的。**「泛型就是不预先确定的数据类型, 具体的类型在使用的时候再确定的一种类型约束规范」**。
4 |
5 | 泛型的好处:
6 |
7 | - 函数和类可以轻松的支持多种类型, 增强程序的扩展性
8 | - 不必写多条函数重载, 冗长的联合类型声明, 增强代码的可读性
9 | - 灵活控制类型之间的约束
10 |
11 | ## 泛型约束
12 |
13 | 有时候我们希望限制每个类型变量**接受的类型数量**, 这就是**泛型约束**。
14 |
15 | 我们可以使用 `,` 号来分隔多种约束类型, 比如: ``。
16 |
17 | ## 常见的一些泛型变量含义
18 |
19 | - T (Type): 表示一个 `TypeScript` 类型
20 |
21 | - K (Key): 表示对象中的键类型
22 |
23 | - V (Value): 表示对象中的值类型
24 |
25 | - E (Element): 表示元素类型
26 |
27 |
28 | ## 使用
29 |
30 | ```ts
31 | function validator(arg: T): T {
32 | return arg;
33 | }
34 | ```
35 |
36 | ## 快来耍耍啊
37 |
38 | ### 🌰🌰
39 |
40 |
41 |
42 | ```
43 | // template
44 | ```
45 |
46 | ### 游乐场
47 |
48 |
49 |
50 |
53 |
54 | ### 参考答案
55 |
56 | ```ts
57 | // answer
58 | ```
59 |
60 | ## 参考资料
61 |
62 | [handbook - generics](https://www.typescriptlang.org/docs/handbook/generics.html)
63 |
64 | [generics](https://basarat.gitbook.io/typescript/type-system/generics)
65 |
66 | [TypeScript Spec](https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md)
67 |
68 | [TypeScript进阶 之 重难点梳理](https://mp.weixin.qq.com/s/xWaVvh5lXG8Nb_U6bmJamw)
69 |
70 | [一文读懂 TypeScript 泛型及应用( 7.8K字)](https://juejin.im/post/6844904184894980104)
71 |
--------------------------------------------------------------------------------
/docs/zh/guide/README.md:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 | [](https://github.com/Rain120/typescript-guide/watchers)
9 | [](https://github.com/Rain120/typescript-guide/stargazers) [](https://github.com/Rain120/typescript-guide/network/members)
10 |
11 | [](https://github.com/Rain120/typescript-guide/issues) [](https://github.com/Rain120/typescript-guide/pulls) [](https://github.com/Rain120/typescript-guide/commits/master)
12 |
13 | 
14 | [](https://github.com/Rain120/typescript-guide/blob/master/package.json) [](https://github.com/Rain120/typescript-guide/blob/master/LICENSE)
15 |
16 |
17 |
18 | ## 😚 Welcome
19 |
20 | Welcome to the Typescript Guide.
21 |
22 | ## 🎮 TL;DR
23 |
24 |
25 | [Document](https://rain120.github.io/typescript-guide/)
26 |
27 | ## ✍ Why am I doing this?
28 |
29 | Write documents for how to easily use typescript.
30 |
31 | ## 🍾 Objective Key Result (OKR)
32 |
33 | ### Objective
34 |
35 | Learning all about the base of Typescript, and practice it
36 |
37 | ### Key Result
38 |
39 | - [x] [Compile Config](../compile-config/README.md)
40 |
41 | - [x] [Basic](../basic/README.md)
42 |
43 | - [x] [Type Assertion](../type-assertion/README.md)
44 |
45 | - [x] [Advanced Types](../advanced-types/README.md)
46 |
47 | - [x] [Intersection Types](../advanced-types/intersection-types/README.md)
48 |
49 | - [x] [Union Types](../advanced-types/union-types/README.md)
50 |
51 | - [x] [Type Guard](../advanced-types/type-guard/README.md)
52 |
53 | - [x] [Nullable](../advanced-types/nullable/README.md)
54 |
55 | - [x] [Array](../array/README.md)
56 |
57 | - [x] [Function](../function/README.md)
58 |
59 | - [ ] [Decorators](../decorators/README.md)
60 |
61 | - [ ] [Class](../class/README.md)
62 |
63 | - [x] [内置对象](../built-in-objects/README.md)
64 |
65 | - [ ] [Interface](../interface/README.md)
66 |
67 | - [ ] [Generics](../generics/README.md)
68 |
69 | - [x] [Operator](../operator/README.md)
70 |
71 | - [x] [Keyword](../keyword/README.md)
72 |
73 | - [x] [is](../keyword/is/README.md)
74 |
75 | - [x] [keyof](../keyword/keyof/README.md)
76 |
77 | - [x] [in](../keyword/in/README.md)
78 |
79 | - [x] [typeof](../keyword/typeof/README.md)
80 |
81 | - [x] [instanceof](../keyword/instanceof/README.md)
82 |
83 | - [x] [extends](../keyword/extends/README.md)
84 |
85 | - [x] [implements](../keyword/implements/README.md)
86 |
87 | - [ ] [infer](../keyword/infer/README.md)
88 |
89 | - [x] [Utility Types](./docs/zh/utility-types/README.md)
90 |
91 | - [ ] [Tips](../tips/README.md)
92 |
93 | - [ ] [FAQs](../faqs/README.md)
94 |
95 |
96 | ⌨️ To be Continue...
97 |
98 |
101 |
102 | ## 🤝 Contributing
103 |
104 | 
105 |
106 | We welcome all contributions. You can submit any ideas as [pull requests](https://github.com/Rain120/typescript-guide/pulls) or as a GitHub [issue](https://github.com/Rain120/typescript-guide/issues).
107 |
108 | [How to write Docs](how-to-write-docs.md)
109 |
110 | ## 🔗 Links
111 |
112 |
113 |
114 | [Online Docs](https://rain120.github.io/typescript-guide/)
115 |
116 | ## 👨🏭 Author
117 |
118 | > Front-End development engineer, technology stack: React + Typescript + Mobx, also used Vue + Vuex for a while
119 |
120 | - [Github](https://github.com/Rain120)
121 | - [知乎](https://www.zhihu.com/people/yan-yang-nian-hua-120/activities)
122 | - [掘金](https://juejin.im/user/57c616496be3ff00584f54db)
123 |
124 | ## 📝 License
125 |
126 | [MIT](https://github.com/Rain120/typescript-guide/blob/master/LICENSE)
127 |
128 | Copyright © 2020-present [Rain120](https://github.com/Rain120).
129 |
130 | ## ☕ Coffee or Tea
131 |
132 | 
133 |
--------------------------------------------------------------------------------
/docs/zh/interface/README.md:
--------------------------------------------------------------------------------
1 | ## Previously
2 |
3 | 接下来我们来了解一下 [面向对象编程 `OOP(object oriented programming)`](https://en.wikipedia.org/wiki/Object-oriented_programming)中一个概念: 接口。
4 |
5 | 接口是一种用来定义程序的协议,它描述可属于任何类或结构的一组相关行为。
6 |
7 | 接口的目的是指明相关或者不相关类的多个对象的共同行为,跟抽象类很相似,可以说接口是更加抽象的抽象类。
8 |
9 | 接口体现了程序设计的多态和高内聚低耦合的设计思想。
10 |
11 | [Java 中的接口有什么作用? - 知乎](https://www.zhihu.com/question/20111251)
12 |
13 | ## 定义
14 |
15 | **接口** 是 `Typescript` 中一个很重要的概念, 主要是对类型的行为进行抽象, 描述, 并进行类型检查
16 |
17 | ## 使用
18 |
19 | ```ts
20 | interface Profile {
21 | name: string;
22 | age?: string | number;
23 | gender: 'MALE' | 'FEMALE';
24 | }
25 | ```
26 |
27 | ## FAQs
28 |
29 | [interface 和 type 有什么异同点?](../faqs/interface-vs-type.md)
30 | ## 快来耍耍啊
31 |
32 | ### 🌰🌰
33 |
34 |
35 |
36 | ```
37 | // template
38 | ```
39 |
40 | ### 游乐场
41 |
42 |
43 |
44 |
47 |
48 | ### 参考答案
49 |
50 | ```ts
51 | // answer
52 | ```
53 |
54 | ## 参考资料
55 |
56 | [interfaces](https://basarat.gitbook.io/typescript/type-system/interfaces)
57 |
58 |
--------------------------------------------------------------------------------
/docs/zh/keyword/README.md:
--------------------------------------------------------------------------------
1 | ## 目录
2 |
3 | :::theorem Typescript 关键字
4 | Typescript 常用关键字解析和使用。
5 | :::
6 |
7 | [TypeScript as 关键字](./as/README.md)
8 |
9 | [TypeScript is 关键字](./is/README.md)
10 |
11 | [TypeScript keyof 关键字](./keyof/README.md)
12 |
13 | [TypeScript in 关键字](./in/README.md)
14 |
15 | [TypeScript typeof 关键字](./typeof/README.md)
16 |
17 | [TypeScript instanceof 关键字](./instanceof/README.md)
18 |
19 | [TypeScript entends 关键字](./entends/README.md)
20 |
21 | [TypeScript implements 关键字](./implements/README.md)
22 |
23 | [TypeScript infer 关键字](./infer/README.md)
24 |
25 | ## 参考资料
26 |
27 | [Typescript Handbook](https://www.typescriptlang.org/docs/handbook/basic-types.html)
28 |
--------------------------------------------------------------------------------
/docs/zh/keyword/as/README.md:
--------------------------------------------------------------------------------
1 | ## Previously
2 |
3 | ```js
4 | const digit = 100000;
5 | // 怎么获取 digit 的长度呢?
6 | digit.length;
7 | ```
8 |
9 | ## 定义
10 |
11 | :::theorem as
12 | 用来手动指定一个值的类型([类型断言 或 类型保护](../../type-assertion/README.md))。换句话来说,就是你比编译器更了解这个变量的类型是什么。
13 | :::
14 |
15 | ## 使用
16 |
17 | ```ts
18 | const someValue: any = "this is a string";
19 | const strLength: number = (someValue as string).length;
20 | ```
21 |
22 | ## 快来耍耍啊
23 |
24 | ### 🌰🌰
25 |
26 |
27 |
28 | ```
29 | // template
30 | ```
31 |
32 | ### 游乐场
33 |
34 |
35 |
36 |
39 |
40 | ### 参考答案
41 |
42 | ```ts
43 | // answer
44 | ```
45 |
46 | ## 参考资料
47 |
48 |
49 |
--------------------------------------------------------------------------------
/docs/zh/keyword/extends/README.md:
--------------------------------------------------------------------------------
1 | ## Previously
2 |
3 | ```js
4 | class Fruit {
5 | name: string;
6 | color: string;
7 | }
8 |
9 | class Apple extends Fruit {
10 | // bla bla
11 | }
12 | ```
13 |
14 | `Class` 可以通过 `extends` 关键字实现继承,这比 `ES5` 的通过修改原型链实现继承,要清晰和方便很多。[More Info](https://es6.ruanyifeng.com/?search=extends&x=0&y=0#docs/class-extends)
15 |
16 | ## 定义
17 |
18 | :::theorem extends
19 | 可以用来继承一个类,也可以用来继承一个 `interface`,但还可以用来判断有条件类型,**接口支持多重继承,语法为逗号隔开**。
20 | :::right
21 | [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html)
22 | :::
23 |
24 | ## 使用
25 |
26 | ### 条件类型
27 |
28 | [Typescript 2.8 新增](https://devblogs.microsoft.com/typescript/announcing-typescript-2-8-2/#conditional-types) `extends` 用来条件类型判断。
29 |
30 | :::tips
31 | 表示条件判断,如果前面的条件满足,则返回问号后的第一个参数,否则第二个。类似于js的三元运算。
32 | :::
33 |
34 | ```ts
35 | T extends U ? X : Y
36 | ```
37 |
38 | 上面的类型表示当 `T` 可分配给 `U` 时,类型为 `X`,否则为 `Y`。
39 |
40 | 原理是令 `T'` 和 `U'` 分别为 `T` 和 `U` 的实例,并将所有类型参数替换为 `any`,如果 `T'` 能赋值给 `U'`,则将有条件的类型解析成 `X`,否则为`Y`。
41 |
42 | ```ts
43 | // Remove types from T that are assignable to U ===> 差集
44 | type Diff = T extends U ? never : T;
45 | // Remove types from T that are not assignable to U ===> 交集
46 | type Filter = T extends U ? T : never;
47 |
48 | type T1 = Diff<"a" | "b" | "c" | "d", "a" | "c" | "f">;
49 | // ^ = type T1 = "b" | "d"
50 | type T2 = Filter<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c"
51 | // ^ = type T2 = "a" | "c"
52 | type T3 = Diff void), Function>; // string | number
53 | // ^ = type T3 = string | number
54 | type T4 = Filter void), Function>; // () => void
55 | // ^ = type T4 = () => void
56 | ```
57 |
58 | 当 `T` 是联合类型时,
59 |
60 | ```ts
61 | (T1 | T2) extends U ? X : Y
62 |
63 | // (T1 extends U | T2 extends U) ? X : Y
64 | ```
65 |
66 | ### 继承
67 |
68 | 像类一样,接口可以互相扩展。 这使您可以将一个接口的成员复制到另一个接口中,从而在如何将接口分离为可重用组件方面提供了更大的灵活性。
69 |
70 | ```ts
71 | interface Shape {
72 | color: string;
73 | }
74 |
75 | interface Square extends Shape {
76 | sideLength: number;
77 | }
78 |
79 | let square = {} as Square;
80 | square.color = "blue";
81 | square.sideLength = 10;
82 | ```
83 |
84 | 一个接口可以扩展多个接口,从而创建所有接口的组合。
85 |
86 | ```ts
87 | interface Shape {
88 | color: string;
89 | }
90 |
91 | interface PenStroke {
92 | penWidth: number;
93 | }
94 |
95 | interface Square extends Shape, PenStroke {
96 | sideLength: number;
97 | }
98 |
99 | let square = {} as Square;
100 | square.color = "blue";
101 | square.sideLength = 10;
102 | square.penWidth = 5.0;
103 | ```
104 |
105 | ### 类继承
106 |
107 | ```ts
108 | interface Profile {
109 | name: string;
110 | age?: string | number;
111 | }
112 |
113 | class Person {
114 | name: string;
115 | age?: string | number;
116 |
117 | constructor(options: Profile) {
118 | this.name = options?.name;
119 | this.age = options?.age;
120 | }
121 | }
122 |
123 | class Boy extends Person {
124 | gender: string
125 | }
126 | ```
127 |
128 | ## 快来耍耍啊
129 |
130 | ### 🌰🌰
131 |
132 |
133 |
134 | ```
135 | // template
136 | ```
137 |
138 | ### 游乐场
139 |
140 |
141 |
142 |
145 |
146 | ### 参考答案
147 |
148 | ```ts
149 | // answer
150 | ```
151 |
152 | ## 参考资料
153 |
154 | [conditional-types](https://www.typescriptlang.org/docs/handbook/advanced-types.html#conditional-types)
155 |
156 | [extending-interfaces](https://www.typescriptlang.org/docs/handbook/interfaces.html#extending-interfaces)
157 |
158 | [whats-the-difference-between-extends-and-implements-in-typescript](https://stackoverflow.com/questions/38834625/whats-the-difference-between-extends-and-implements-in-typescript)
159 |
--------------------------------------------------------------------------------
/docs/zh/keyword/implements/README.md:
--------------------------------------------------------------------------------
1 | ## Previously
2 |
3 | 请先行了解 👉 [Interface](../../interface/README.md)。
4 | ## 定义
5 |
6 | :::theorem implements
7 | [implements (实现)](https://en.wikipedia.org/wiki/Implement) 是面向对象中的一个重要概念。它是要实现一个已经定义好的接口中的方法。
8 | :::
9 | ## 使用
10 |
11 | ### 接口实现
12 |
13 | ```ts
14 | interface Shape {
15 | color: string;
16 | draw(): void;
17 | }
18 | class DrawShape implements Shape {
19 | color: string;
20 |
21 | constructor(color: string) {
22 | this.color = color;
23 | }
24 |
25 | draw() {
26 | console.log(`draw shape with ${this.color}`);
27 | }
28 | }
29 | ```
30 |
31 | 一个类可以实现多个接口
32 |
33 | ```ts
34 | interface Shape {
35 | color: string;
36 | draw(): void;
37 | }
38 |
39 | interface Paint {
40 | paint(): void;
41 | }
42 |
43 | class DrawShape implements Shape, Paint {
44 | color: string;
45 |
46 | constructor(color: string) {
47 | this.color = color;
48 | }
49 |
50 | draw() {
51 | console.log(`draw shape with ${this.color}`);
52 | }
53 |
54 | paint() {
55 | console.log(`draw shape with ${this.color}`);
56 | }
57 | }
58 | ```
59 |
60 |
61 |
62 | ## 快来耍耍啊
63 |
64 | ### 🌰🌰
65 |
66 |
67 |
68 | ```
69 | // template
70 | ```
71 |
72 | ### 游乐场
73 |
74 |
75 |
76 |
79 |
80 | ### 参考答案
81 |
82 | ```ts
83 | // answer
84 | ```
85 |
86 | ## 参考资料
87 |
88 | [whats-the-difference-between-extends-and-implements-in-typescript](https://stackoverflow.com/questions/38834625/whats-the-difference-between-extends-and-implements-in-typescript)
89 |
--------------------------------------------------------------------------------
/docs/zh/keyword/in/README.md:
--------------------------------------------------------------------------------
1 | ## Previously
2 |
3 | 如果指定的属性在指定的对象或其原型链中,则 `in` 运算符返回 `true`。
4 |
5 | ```js
6 | const car = { make: 'Honda', model: 'Accord', year: 1998 };
7 |
8 | console.log('make' in car);
9 | // expected output: true
10 |
11 | delete car.make;
12 | if ('make' in car === false) {
13 | car.make = 'Suzuki';
14 | }
15 |
16 | console.log(car.make);
17 | // expected output: "Suzuki"
18 |
19 | ```
20 |
21 | ## 定义
22 |
23 | :::theorem in
24 | 用来遍历枚举类型。
25 | :::
26 |
27 | ## 使用
28 |
29 | ```ts
30 | type Keys = 'name' | 'age';
31 |
32 | interface Profile {
33 | [P in Keys]: string;
34 | }
35 |
36 | /**
37 | * interface Profile {
38 | * name: string;
39 | * age: string;
40 | * }
41 | *
42 | */
43 |
44 | ```
45 |
46 | ## 快来耍耍啊
47 |
48 | ### 🌰🌰
49 |
50 |
51 |
52 | ```
53 | // template
54 | ```
55 |
56 | ### 游乐场
57 |
58 |
59 |
60 |
63 |
64 | ### 参考答案
65 |
66 | ```ts
67 | // answer
68 | ```
69 |
70 | ## 参考资料
71 |
72 |
73 |
--------------------------------------------------------------------------------
/docs/zh/keyword/infer/README.md:
--------------------------------------------------------------------------------
1 | ## 定义
2 |
3 | `infer` 最早出现在此 [PR](https://github.com/Microsoft/TypeScript/pull/21496) 中, 表示在 `extends` 条件语句中待推断的类型变量。
4 |
5 | `infer` 关键词常在条件类型中和 `extends` 关键词一同出现, 表示**将要推断的类型, 作为类型变量可以在三元表达式的 `true` 部分引用**。而 `ReturnType` 正是使用这种方式提取到了函数的返回类型。
6 |
7 | 使用 `infer`, 编译器确保您已经显式声明了所有类型变量。
8 |
9 | ## 使用
10 |
11 | ```ts
12 | type Unpacked = T extends (infer U)[]
13 | ? U
14 | : T extends (...args: any[]) => infer U
15 | ? U
16 | : T extends Promise
17 | ? U
18 | : T;
19 |
20 | type T0 = Unpacked; // string
21 | type T1 = Unpacked; // string
22 | type T2 = Unpacked<() => string>; // string
23 | type T3 = Unpacked>; // string
24 | type T4 = Unpacked[]>; // Promise
25 | type T5 = Unpacked[]>>; // string
26 | ```
27 |
28 | `infer` 可以用来推断联合类型
29 |
30 | ```ts
31 | type Foo = T extends {a: infer U; b: infer U} ? U : never;
32 |
33 | type T10 = Foo<{a: string; b: string}>; // string
34 | type T11 = Foo<{a: string; b: number}>; // string | number
35 | ```
36 |
37 | 同样,在变数位置中针对同一类型变量的多个候选会导致得出交集类型:
38 |
39 | ```ts
40 | type Bar = T extends {a: (x: infer U) => void; b: (x: infer U) => void} ? U : never;
41 | type T20 = Bar<{a: (x: string) => void; b: (x: string) => void}>; // string
42 | type T21 = Bar<{a: (x: string) => void; b: (x: number) => void}>; // string & number
43 | ```
44 |
45 | ## 内置类型
46 |
47 | ### 用于提取函数类型的返回值类型
48 |
49 | ```ts
50 | /**
51 | * 获取函数 T 的返回类型
52 | */
53 | type ReturnType any> = T extends (...args: any) => infer R ? R : any;
54 | ```
55 |
56 | 更多有关于 `ReturnType` [Here](../../utility-types/#returntype-t)
57 |
58 | #### Demo
59 |
60 | ```ts
61 | type Func = (...args: any) => string | number;
62 |
63 | type ReturnValue = ReturnType; // string | number
64 | ```
65 |
66 | ### 用于提取构造函数中参数 (实例) 类型
67 |
68 | 构造函数可以使用 `new` 来实例化, 因此它的类型通常表示如下:
69 |
70 | ```ts
71 | type Constructor = new (...ages: any[]) => any;
72 | ```
73 |
74 | 当 `infer` 用于构造函数类型中, 可用于参数位置 `new (...args: infer P) => any` 和 返回值位置 `new (...args: any[]) => infer P`。
75 |
76 | 因此就内置如下两个映射类型:
77 |
78 | ```ts
79 | // 获取参数类型
80 | type ConstructorParameters any> = T extends new (
81 | ...args: infer P
82 | ) => any
83 | ? P
84 | : never;
85 |
86 | // 获取实例类型
87 | type InstanceType any> = T extends new (...args: any[]) => infer R
88 | ? R
89 | : any;
90 | ```
91 |
92 | #### Demo
93 |
94 | ```ts
95 | class TestClass {
96 | constructor(public name: string, public string: number) {}
97 | }
98 |
99 | type Params = ConstructorParameters; // [string, numbder]
100 |
101 | type Instance = InstanceType; // TestClass
102 | ```
103 |
104 | ## 快来耍耍啊
105 |
106 | ### 🌰🌰
107 |
108 |
109 |
110 | ```
111 | // template
112 | ```
113 |
114 | ### 游乐场
115 |
116 |
117 |
118 |
121 |
122 | ### 参考答案
123 |
124 | ```ts
125 | // answer
126 | ```
127 |
128 | ## 参考资料
129 |
130 | [infer PR: Type inference in conditional types](https://github.com/Microsoft/TypeScript/pull/21496)
131 |
132 | [typescript-2-8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html)
133 |
134 | [type-inference-in-conditional-types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#type-inference-in-conditional-types)
135 |
136 | [TypeScript 面试题](https://github.com/LeetCode-OpenSource/hire/blob/master/typescript_zh.md)
--------------------------------------------------------------------------------
/docs/zh/keyword/instanceof/README.md:
--------------------------------------------------------------------------------
1 | ## Previously
2 |
3 | `instanceof` 运算符用于检测构造函数的 `prototype` 属性是否出现在某个实例对象的原型链上。
4 |
5 | ```js
6 | function Car(make, model, year) {
7 | this.make = make;
8 | this.model = model;
9 | this.year = year;
10 | }
11 | const auto = new Car('Honda', 'Accord', 1998);
12 |
13 | console.log(auto instanceof Car);
14 | // expected output: true
15 |
16 | console.log(auto instanceof Object);
17 | // expected output: true
18 | ```
19 |
20 |
21 | ## 定义
22 |
23 | :::theorem instanceof
24 | `instanceof` 通过 **构造函数** 来细化类型, 用来检测实例与 **类** 的所属关系。
25 | :::
26 |
27 | **Note:**
28 |
29 | - 参数: `instanceof` 在左侧使用变量名称, 在左侧使用函数或类的名称。
30 | - 返回: `Boolean` 值。
31 |
32 | ## 使用
33 |
34 | ```ts
35 | interface Person {
36 | name: string;
37 | age: string | number;
38 | }
39 |
40 | const mine: Person = {
41 | name: 'Rain120',
42 | age: 18
43 | }
44 |
45 | const isPerson = typeMine instanceof Person; // true
46 | ```
47 |
48 | ## 快来耍耍啊
49 |
50 | ### 🌰🌰
51 |
52 |
53 |
54 | ```
55 | // template
56 | ```
57 |
58 | ### 游乐场
59 |
60 |
61 |
62 |
65 |
66 | ### 参考答案
67 |
68 | ```ts
69 | // answer
70 | ```
71 |
72 | ## 参考资料
73 |
74 | [instanceof-guard](https://alligator.io/typescript/instanceof-guard/)
75 |
76 |
77 |
--------------------------------------------------------------------------------
/docs/zh/keyword/is/README.md:
--------------------------------------------------------------------------------
1 | ## Previously
2 |
3 | ```ts
4 | function isString(value: any): boolean {
5 | // toExponential() 方法以指数表示法返回该数值字符串表示形式。numObj = 77.1234; => numObj.toExponential(2) //输出 7.71e+1
6 | console.log(value.toExponential(2));
7 | return value === 'string';
8 | }
9 | ```
10 |
11 | ## 定义
12 |
13 | :::theorem is
14 | `is` 关键字被称为类型谓词, 它表示是否属于某个类型, 可以有效地缩小类型范围, 它可以帮助开发者在编辑阶段发现错误,从而避免一些隐藏的运行时错误。
15 | :::
16 |
17 | 作用: 既可以作为返回值,也可以缩小变量(函数内部会校验类型)的类型范围。
18 |
19 | ## 使用
20 |
21 | ```ts
22 | // incorrect
23 | function isString(value: any): boolean {
24 | // toExponential() 方法以指数表示法返回该数值字符串表示形式。
25 | console.log(value.toExponential(2));
26 | return typeof value === 'string';
27 | }
28 |
29 | // 使用 Demo
30 | function isString_is(value: any): value is string {
31 | return typeof value === 'string';
32 | }
33 |
34 | function testString(string: any) {
35 | if (isString(string)) {
36 | console.log(string.length)
37 | console.log(string.toExponential(2))
38 | }
39 |
40 | // 测试 is 收窄范围和普通模式下的优势
41 | if (isString_is(string)) {
42 | console.log(string.length)
43 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toExponential
44 | // Property 'toExponential' does not exist on type 'string'.(2339)
45 | console.log(string.toExponential(2))
46 | }
47 | }
48 |
49 | testString('female');
50 |
51 | ```
52 |
53 | [直接体验](https://www.typescriptlang.org/play?#code/PTAEEsDsGMHsCd4FNoBcBQAzArjV5ZIIBnAZVXigHMAKANwEMAbbJALlAcgE8BKDgEaxYTJF1ABvdAEgQoVLACiADwAOhJJHzMavUIE7TQKs2gU7lA4MaAHU0AWEYC5PQ4BX4wHtqgU+jzgHgVA6tqAyb0BMcjcBG+oDw+oBADOigoHCQxCJIAHRMsLSMLLEKKuqQmtpMNABMvLwA3KGgyKjY8ESo3KpIsJigSaygALytoADkxBTU7UUAvujocoD+8oAUrqAAIkgAtrBYuGgEROBk3ZBUAPor9MysHFx8HI1IJKBdlOuSxaXlldW19cctbZ1rVL3oA-N4S-JIXeQLrRztR9jw9FIwuB6jQVoDqDQQet8lcwmEIlFRHEEoi3nFNFRUAALXjFdGETGxeLAvGpNQaLTgHR5UlhL5hOSAaVtAKvRp0AbKaAEK9AMDBgBe1QAxKoA7M0AWAmAQisAoBoOUAIW6ADHlAP1KxWhoFhqyBW2IuKBKMhaIx0WxNKB+PWxNZaLkRNQqFUxDYIAAJkg6Eh4jV4DFZgAvcBMJgMGIIKjATQAWgAqqRgG7YNBiMAAOpIATAABSDEYpGglFUqGAACUkJgkMgYEhgABxeICZgbADyAgAVihUKmAHLYaYCKvAOnpTJMphk0ByAAK8FgvqqHRHDKy7VASf+oEgsFQoCQyhWu8I8nuHSR7xiuQAzFeAJy28mRM3Ug3UGLLjKM5n5YoDL6of5UHhdYaHaStpmYJB2kKIA)
54 |
55 | ## 快来耍耍啊
56 |
57 | ### 🌰🌰
58 |
59 |
60 |
61 | ```
62 | // template
63 | ```
64 |
65 | ### 游乐场
66 |
67 |
68 |
69 |
72 |
73 | ### 参考答案
74 |
75 | ```ts
76 | // answer
77 | ```
78 |
79 | ## 参考资料
80 |
81 | [what-does-the-is-keyword-do-in-typescript](https://stackoverflow.com/questions/40081332/what-does-the-is-keyword-do-in-typescript)
82 |
--------------------------------------------------------------------------------
/docs/zh/keyword/keyof/README.md:
--------------------------------------------------------------------------------
1 | ## Previously
2 |
3 | `JavaScript` 是一种动态语言。有时在静态类型系统中捕获某些操作的语义可能会很棘手。
4 |
5 | ```js
6 | function prop(obj, key) {
7 | return obj && obj[key] ? obj[key] : null; // lodash.get(prop, key)
8 | }
9 | ```
10 |
11 | 该函数接收 `obj` 和 `key` 两个参数,并返回对应属性的值。对象上的不同属性,可以具有完全不同的类型,我们甚至不知道 `obj` 对象长什么样。
12 |
13 | ```ts
14 | function prop(obj, key: string) {
15 | return (obj as any)[key];
16 | }
17 | ```
18 | ## 定义
19 |
20 | :::theorem keyof
21 | `keyof` 也称为输入索引类型查询, 与之相对应的是索引访问类型, 也称为查找类型, 用来取得一个对象接口(某种类型)的所有 `key` 值, 返回一个联合类型。
22 |
23 | :::right
24 | [Typescript 2.1 新增](https://devblogs.microsoft.com/typescript/announcing-typescript-2-1-2/#keyof-and-lookup-types)
25 | :::
26 |
27 | ## 如何解决上述问题
28 |
29 | ```ts
30 | type Todo = {
31 | id: number;
32 | text: string;
33 | done: boolean;
34 | }
35 |
36 | const todo: Todo = {
37 | id: 1,
38 | text: "Learn TypeScript keyof",
39 | done: false
40 | }
41 |
42 | // extends 关键字约束该类型必须是 object 类型的子类型
43 | function prop(obj: T, key: K) {
44 | return obj[key];
45 | }
46 |
47 | // number
48 | const id = prop(todo, "id");
49 |
50 | // string
51 | const text = prop(todo, "text");
52 |
53 | // boolean
54 | const done = prop(todo, "done");
55 |
56 | ```
57 |
58 | ## 使用
59 |
60 | ```ts
61 | interface Profile {
62 | name: string;
63 | age: number;
64 | }
65 |
66 | // 'name' | 'age'
67 | type Keys = keyof Profile;
68 |
69 | // 'string' | 'number'
70 | type TypeKeys = keyof { [K: string]: Profile};
71 | ```
72 |
73 | ### 访问值
74 |
75 | 可通过 **T[K]** 索引访问。
76 |
77 | ```ts
78 | interface Profile {
79 | name: string,
80 | readonly age: number,
81 | }
82 |
83 | // string
84 | type Name = Profile['name']
85 |
86 | // string | number
87 | type NameAge = Profile['name' | 'age']
88 |
89 | // 如果[]中的key有不存在T中的,则是any;
90 | // 因为ts也不知道该key最终是什么类型,所以是any;
91 | // 且也会报错
92 | // any
93 | type GetValueFromUnknownKey = Profile['name' | 'unknownKey']
94 |
95 | // string | number
96 | type ProfileValue = Profile[keyof Profile]
97 |
98 | ```
99 |
100 | ## ⚠️ 注意
101 |
102 | 对于 **任何类型T**, **keyof T**的结果为该类型上所有 **公有(public)属性key** 的联合。
103 |
104 | ```ts
105 | interface Profile {
106 | name: string,
107 | readonly age: number,
108 | }
109 |
110 | // ProfileKeys 的类型实则是 name | age
111 | type ProfileKeys = keyof Profile;
112 |
113 | class PersonProfile {
114 | private name: string;
115 | protected home: string;
116 | public readonly age: number;
117 | }
118 |
119 | // PersonProfileKeys 实则被约束为 age
120 | // 而 name 和 home 不是公有属性,所以不能被 keyof 获取到
121 | type PersonProfileKeys = keyof PersonProfile;
122 | ```
123 |
124 | ## 快来耍耍啊
125 |
126 | ### 🌰🌰
127 |
128 |
129 |
130 | ```
131 | // template
132 | ```
133 |
134 | ### 游乐场
135 |
136 |
137 |
138 |
141 |
142 | ### 参考答案
143 |
144 | ```ts
145 | // answer
146 | ```
147 |
148 | ## 参考资料
149 |
150 | [TypeScript keyof 操作符](https://cloud.tencent.com/developer/article/1595718)
151 |
--------------------------------------------------------------------------------
/docs/zh/keyword/typeof/README.md:
--------------------------------------------------------------------------------
1 | ## Previously
2 |
3 | `typeof` 只能校验基本类型只能返回这种类型, `undefined`, `boolean`, `string`, `number`, `object`, `function`。
4 |
5 | ## 定义
6 |
7 | :::theorem typeof
8 | 用于获取变量的声明类型。
9 | :::
10 |
11 | **Note:**
12 |
13 | - 参数: `typeof` 只接受我们正在检查其变量类型的变量的名称, 该变量的名称在右侧, 而左侧则没有。
14 |
15 | - 返回: `类型 (Type)` 的值。
16 |
17 | ## 使用
18 |
19 | ```ts
20 | function getType(val: any) {
21 | return typeof val;
22 | }
23 |
24 | getType('name'); // string
25 |
26 | const COLORS = {
27 | red: 'red',
28 | blue: 'blue'
29 | }
30 |
31 | // 通过 typeof 操作符获取 color 变量的类型
32 | type Type = typeof COLORS
33 | // {
34 | // red: string;
35 | // blue: string;
36 | // }
37 | ```
38 |
39 | ## 快来耍耍啊
40 |
41 | ### 🌰🌰
42 |
43 |
44 |
45 | ```
46 | // template
47 | ```
48 |
49 | ### 游乐场
50 |
51 |
52 |
53 |
56 |
57 | ### 参考答案
58 |
59 | ```ts
60 | // answer
61 | ```
62 |
63 | ## 参考资料
64 |
65 |
66 |
--------------------------------------------------------------------------------
/docs/zh/operator/README.md:
--------------------------------------------------------------------------------
1 | ## 定义
2 |
3 | 运算符定义一些将对数据, 变量执行的功能。 运算符所作用的数据称为操作数或者操作变量。
4 |
5 | ## & 运算符
6 |
7 | [交叉类型](../advanced-types/intersection-types/)
8 |
9 | ```ts
10 | interface Boy {
11 | handsome: boolean;
12 | }
13 |
14 | interface Girl {
15 | cute: boolean;
16 | }
17 |
18 | type Person = Boy & Girl;
19 |
20 | const someone: Person = {
21 | handsome: true,
22 | cute: false
23 | };
24 | ```
25 |
26 | ## | 运算符
27 |
28 | [联合类型](../advanced-types/union-types/)
29 |
30 | ```ts
31 | interface Boy {
32 | hair: boolean;
33 | tall: boolean;
34 | }
35 |
36 | interface Girl {
37 | hair: boolean;
38 | cute: boolean;
39 | }
40 |
41 | type Person = Boy | Girl
42 |
43 | const someone: Person = {
44 | hair: true
45 | }
46 | ```
47 |
48 | ## ! 非空断言操作符
49 |
50 | 表达式不能为 `null` 或 `undefined` 的方式
51 |
52 | > `!`在类型检查器无法得出结论的情况下,可以使用新的后缀表达式运算符来断言其操作数为非`null`且未定义。具体来说,操作`x!`生成一个类型为`x`的值,不包含 `null` 和 `undefined`的值。类似于表单`x`和的类型声明`x as T`。
53 | >
54 | > **Note:** `!`非空断言操作符会从编译生成的 `JavaScript` 代码中移除。
55 |
56 | ```typescript
57 | class C {
58 | foo!: number;
59 | // ^
60 | // Notice this '!' modifier.
61 | // This is the "definite assignment assertion"
62 |
63 | constructor() {
64 | this.initialize();
65 | }
66 |
67 | initialize() {
68 | this.foo = 0;
69 | }
70 | }
71 | ```
72 |
73 | ### 忽略 null 和 undefined 类型
74 |
75 | ```ts
76 | const profile: any = {
77 | name: 'Rain120',
78 | schools: {}
79 | }
80 |
81 | const getProfile(profile: any) {
82 | console.log(profile!.name, profile!.age, profile!.schools!)
83 | }
84 |
85 | getProfile(profile);
86 | getProfile();
87 | ```
88 |
89 | ### 忽略函数 undefined 类型
90 |
91 | ```ts
92 | const curry = (fn: any) => {
93 | return fn!();
94 | }
95 | ```
96 |
97 | **Note:**
98 |
99 | 出现下面情况,需要注意一下,因为`!`非空断言操作符会从编译生成的 `JavaScript` 代码中移除。
100 |
101 | ```ts
102 | const name: undefined | string = undefined;
103 | const getName: string = name!;
104 | console.log(getName);
105 |
106 | // 转换成 ES5 ===>
107 | "use strict";
108 | const name = undefined;
109 | const getName = name;
110 | console.log(getName);
111 | ```
112 |
113 | [严格的属性初始化](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#strict-class-initialization)
114 |
115 | [非null断言运算符](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator)
116 |
117 | ## ? 运算符
118 |
119 | - 定义属性用于 **可选属性定义**
120 |
121 | ```typescript
122 | interface Profile {
123 | name: string;
124 | age?: number | string;
125 | }
126 | ```
127 |
128 | [optional-properties](https://www.typescriptlang.org/docs/handbook/interfaces.html#optional-properties)
129 |
130 | - 使用属性用于 **可选的属性访问**
131 |
132 | ### ?. 运算符
133 |
134 | **?.** 只会检查其左侧的值是否为 `null` 或 `undefined`, 而不检查任何后续属性。
135 |
136 | ```ts
137 | const x = foo?.bar.baz
138 |
139 | // ===>
140 |
141 | const x = (foo === null || foo === undefined)
142 | ? undefined
143 | : foo.bar.baz();
144 | ```
145 |
146 | **Note:** `typescript 3.7+`才支持。
147 |
148 | [optional-chaining](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html?#optional-chaining)
149 |
150 | [Announcing TypeScript 3.7 RC](https://devblogs.microsoft.com/typescript/announcing-typescript-3-7-rc/) -> [译文](https://www.infoq.cn/article/d95pGayR9s4eucUGKSFP)
151 |
152 | ### ?? 运算符
153 |
154 | **空值合并运算符** 是即将推出的另一个 `ECMAScript 2020`功能, 它与可选的链接并驾齐驱。
155 |
156 | **当左侧操作数为 null 或 undefined 时,其返回右侧的操作数,否则返回左侧的操作数**。
157 |
158 | ```ts
159 | let x = foo ?? bar();
160 |
161 | // ===>
162 |
163 | let x = (foo !== null && foo !== undefined)
164 | ? foo
165 | : bar();
166 | ```
167 |
168 | [nullish-coalescing](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#nullish-coalescing)
169 |
170 | ## + - 运算符
171 |
172 | `TypeScript 2.8` 为映射类型增加了增加或移除特定修饰符的能力。 特别地, 映射类型里的`readonly`或`?`属性修饰符现在可以使用`+`或`-`前缀, 来表示修饰符是添加还是移除。
173 |
174 | ```ts
175 | type MutableRequired = {
176 | -readonly [P in keyof T]-?: T[P]
177 | }; // 移除readonly和?
178 | type ReadonlyPartial = {
179 | +readonly [P in keyof T]+?: T[P]
180 | }; // 添加readonly和?
181 | ```
182 |
183 | [改进对映射类型修饰符的控制](http://www.tslang.cn/docs/release-notes/typescript-2.8.html)
184 |
185 | ## _ 运算符
186 |
187 | TypeScript 2.7支持ECMAScript的数字分隔符提案。 这个特性允许用户在数字之间使用下划线(_)来对数字分组(就像使用逗号和点来对数字分组那样)。
188 |
189 | ```ts
190 | // Constants
191 | const COULOMB = 8.957_551_787e9; // N-m^2 / C^2
192 | const PLANCK = 6.626_070_040e-34; // J-s
193 | const JENNY = 867_5309; // C-A-L^2
194 | ```
195 |
196 | 这些分隔符对于二进制和十六进制同样有用。
197 |
198 | ```ts
199 | let bits = 0b0010_1010;
200 | let routine = 0xC0FFEE_F00D_BED;
201 | let martin = 0xF0_1E_
202 | ```
203 |
204 | 注意,可能有些反常识,`JavaScript`里的数字表示信用卡和电话号并不适当。 这种情况下使用字符串更好。
205 |
206 | [数字分隔符](https://www.tslang.cn/docs/release-notes/typescript-2.7.html)
207 |
208 | ## \# 运算符
209 |
210 | TypeScript 3.8 支持在 ECMAScript 中处于 [stage-3](https://github.com/tc39/proposal-class-fields/) 中的私有字段。
211 |
212 | ```ts
213 | class Person {
214 | #name: string
215 |
216 | constructor(name: string) {
217 | this.#name = name;
218 | }
219 |
220 | greet() {
221 | console.log(`Hello, my name is ${this.#name}!`);
222 | }
223 | }
224 |
225 | let jeremy = new Person("Jeremy Bearimy");
226 |
227 | jeremy.#name
228 | // ~~~~~
229 | // Property '#name' is not accessible outside class 'Person'
230 | // because it has a private identifier.
231 | ```
232 |
233 | 不同于正常属性(甚至是使用 `private` 修饰符声明的属性),私有字段有一些需要记住的规则:
234 |
235 | - 私有字段使用 `#` 字符作为开始,通常,我们也把这些称为私有名称。
236 | - 每个私有字段的名字,在被包含的类中,都是唯一的
237 | - 在 TypeScript 中,像 `public` 和 `private` 修饰符不能用于私有字段
238 | - 私有字段不能在所包含的类之外访问 —— 即使是对于 JavaScript 使用者来说也是如此。通常,我们把这种称为「hard privacy」。
239 |
240 | 除了「hard privacy」,私有字段的另外一个优点是我们先前提到的唯一性。
241 |
242 | 正常的属性容易被子类所改写
243 |
244 | ```ts
245 | class C {
246 | foo = 10;
247 |
248 | cHelper() {
249 | return this.foo;
250 | }
251 | }
252 |
253 | class D extends C {
254 | foo = 20;
255 |
256 | dHelper() {
257 | return this.foo;
258 | }
259 | }
260 |
261 | let instance = new D();
262 | // 'this.foo' refers to the same property on each instance.
263 | console.log(instance.cHelper()); // prints '20'
264 | console.log(instance.dHelper()); // prints '20'
265 | ```
266 |
267 | 使用私有字段时,你完全不必对此担心,因为每个私有字段,在所包含的类中,都是唯一的
268 |
269 | ```ts
270 | class C {
271 | #foo = 10;
272 |
273 | cHelper() {
274 | return this.#foo;
275 | }
276 | }
277 |
278 | class D extends C {
279 | #foo = 20;
280 |
281 | dHelper() {
282 | return this.#foo;
283 | }
284 | }
285 |
286 | let instance = new D();
287 | // 'this.#foo' refers to a different field within each class.
288 | console.log(instance.cHelper()); // prints '10'
289 | console.log(instance.dHelper()); // prints '20'
290 | ```
291 |
292 | 另外有一个值得注意的地方,访问一个有其他类型的私有字段,都将导致 `TypeError`。
293 |
294 | ```ts
295 | class Square {
296 | #sideLength: number;
297 |
298 | constructor(sideLength: number) {
299 | this.#sideLength = sideLength;
300 | }
301 |
302 | equals(other: any) {
303 | return this.#sideLength === other.#sideLength;
304 | }
305 | }
306 |
307 | const a = new Square(100);
308 | const b = { sideLength: 100 };
309 |
310 | // Boom!
311 | // TypeError: attempted to get private field on non-instance
312 | // This fails because 'b' is not an instance of 'Square'.
313 | console.log(a.equals(b));
314 | ```
315 |
316 | 对于类属性来说,`JavaScript` 总是允许使用者访问没被声明的属性,而 TypeScript 需要使用者在访问之前先定义声明。使用私有字段时,无论时 `.js` 文件还是 `.ts`,都需要先声明。
317 |
318 | ```ts
319 | class C {
320 | /** @type {number} */
321 | #foo;
322 |
323 | constructor(foo: number) {
324 | // This works.
325 | this.#foo = foo;
326 | }
327 | }
328 | ```
329 |
330 | 更多信息,请查看此 [PR](https://github.com/Microsoft/TypeScript/pull/30829)。
331 |
332 | ### 私有字段与 private 的区别
333 |
334 | 说到这里使用 `#` 定义的私有字段与 `private` 修饰符定义字段有什么区别呢?现在我们先来看一个 `private` 的示例:
335 |
336 | ```ts
337 | class Person {
338 | constructor(private name: string) {}
339 | }
340 |
341 | let person = new Person("Semlinker");
342 | console.log(person.name);
343 | ```
344 |
345 | 在上面代码中,我们创建了一个 `Person` 类,该类中使用 `private` 修饰符定义了一个私有属性 `name`,接着使用该类创建一个 `person` 对象,然后通过 `person.name` 来访问 `person` 对象的私有属性,这时 `TypeScript` 编译器会提示以下异常:
346 |
347 | ```
348 | Property 'name' is private and only accessible within class 'Person'.(2341)
349 | ```
350 |
351 | 那如何解决这个异常呢?当然你可以使用类型断言把 person 转为 any 类型:
352 |
353 | ```ts
354 | console.log((person as any).name);
355 | ```
356 |
357 | 通过这种方式虽然解决了 TypeScript 编译器的异常提示,但是在运行时我们还是可以访问到 `Person` 类内部的私有属性,为什么会这样呢?我们来看一下编译生成的 ES5 代码,也许你就知道答案了:
358 |
359 | ```ts
360 | var Person = (function () {
361 | function Person(name) {
362 | this.name = name;
363 | }
364 | return Person;
365 | }());
366 |
367 | var person = new Person("Semlinker");
368 | console.log(person.name);
369 | ```
370 |
371 | 在 TypeScript 3.8 以上版本通过 `#` 号定义的私有字段编译后会生成什么代码:
372 |
373 | ```ts
374 | class Person {
375 | #name: string;
376 |
377 | constructor(name: string) {
378 | this.#name = name;
379 | }
380 |
381 | greet() {
382 | console.log(`Hello, my name is ${this.#name}!`);
383 | }
384 | }
385 | ```
386 |
387 | 以上代码目标设置为 `ES2015`,会编译生成以下代码:
388 |
389 | ```js
390 | "use strict";
391 | var __classPrivateFieldSet = (this && this.__classPrivateFieldSet)
392 | || function (receiver, privateMap, value) {
393 | if (!privateMap.has(receiver)) {
394 | throw new TypeError("attempted to set private field on non-instance");
395 | }
396 | privateMap.set(receiver, value);
397 | return value;
398 | };
399 |
400 | var __classPrivateFieldGet = (this && this.__classPrivateFieldGet)
401 | || function (receiver, privateMap) {
402 | if (!privateMap.has(receiver)) {
403 | throw new TypeError("attempted to get private field on non-instance");
404 | }
405 | return privateMap.get(receiver);
406 | };
407 |
408 | var _name;
409 | class Person {
410 | constructor(name) {
411 | _name.set(this, void 0);
412 | __classPrivateFieldSet(this, _name, name);
413 | }
414 | greet() {
415 | console.log(`Hello, my name is ${__classPrivateFieldGet(this, _name)}!`);
416 | }
417 | }
418 | _name = new WeakMap();
419 | ```
420 |
421 | 通过观察上述代码,使用 `#` 号定义的 `ECMAScript` 私有字段,会通过 WeakMap 对象来存储,同时编译器会生成 `__classPrivateFieldSet` 和 `__classPrivateFieldGet` 这两个方法用于设置值和获取值。
422 |
423 | [ECMAScript Private Fields](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#ecmascript-private-fields)
424 |
425 | ## 快来耍耍啊
426 |
427 | ### 🌰🌰
428 |
429 |
430 |
431 | ```
432 | // template
433 | ```
434 |
435 | ### 游乐场
436 |
437 |
438 |
439 |
442 |
443 | ## 参考答案
444 |
445 | ```ts
446 | // answer
447 | ```
448 |
449 | ## 参考资料
450 |
451 | [What's new in TypeScript](https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript)
452 |
453 | [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#ecmascript-private-fields)
454 |
455 | [ECMAScript feature: numeric separators](https://2ality.com/2018/02/numeric-separators.html)
456 |
457 | [细数 TS 中那些奇怪的符号](https://www.yuque.com/arvinxx-fe/typescript/dfe2722f-0c2a-4189-b2c5-de128f85d40f#d958e3d1)
458 |
--------------------------------------------------------------------------------
/docs/zh/tips/README.md:
--------------------------------------------------------------------------------
1 | ## Tips 列表
2 |
3 | [if else](./if-else/README.md)
4 |
5 | [spread](./spread/README.md)
6 |
--------------------------------------------------------------------------------
/docs/zh/tips/if-else/README.md:
--------------------------------------------------------------------------------
1 | ## 定义
2 |
3 | 条件类型,条件类型冒号左边为 if 右边为 else
4 |
5 | ## 使用
6 |
7 | ```ts
8 | type If = T extends K ? true : false;
9 |
10 | type IfValue = T extends true ? K : L;
11 | ```
12 |
13 | ## 快来耍耍啊
14 |
15 | ### 🌰🌰
16 |
17 |
18 |
19 | ```ts
20 | type A = { name: string }
21 | type B = { name: string; age?: number | string }
22 |
23 | type x = If
24 |
25 | type xA = IfValue
26 | type xB = IfValue
27 |
28 | ```
29 |
30 | [Go Demo](https://www.typescriptlang.org/play?#code/C4TwDgpgBAkgZgHgCoBooGkB8UC8UlQQAewEAdgCYDOGUA-FMAE4Cu0AXFHAIYA2VEANwAoYaEiw4ANT5tkhEuWpQARgHs1vCNzJp0aADLY8BYqUo1mberU4GRY8NACCuKAG8oZbgFsInKmYASzIAcygAX0cJACE3T28-AOCwwShuUIg6TjIWHxUIJigAHyhAphDwqOjoIjd4BGc0GMxRcVrXPHgZXjkrCDQmqBaaqCI4rulZCAQefgGoIZagA)
31 |
32 | ### 游乐场
33 |
34 |
35 |
36 |
39 |
40 | ### 参考答案
41 |
42 | ```ts
43 | // answer
44 | ```
45 |
46 | ## 参考资料
47 |
48 |
49 |
--------------------------------------------------------------------------------
/docs/zh/tips/spread/README.md:
--------------------------------------------------------------------------------
1 | ## 定义
2 |
3 | 拓展运算符
4 |
5 | ## 使用
6 |
7 | ```ts
8 | type spreadFirst = T extends [infer First, ...infer Rest] ? First : never;
9 |
10 | type spreadLast = T extends [...infer First, infer Last] ? Last : never;
11 |
12 | type spreadFirstChar = T extends `${infer First}${infer Rest}`? First : never;
13 |
14 | type spreadRestChar = T extends `${infer First}${infer Rest}`? Rest : never;
15 | ```
16 |
17 | ## 快来耍耍啊
18 |
19 | ### 🌰🌰
20 |
21 |
22 |
23 | ```ts
24 | type Arr = [1, 2, 3]
25 | type Str = '123'
26 | type Num = 123
27 |
28 | type FA = spreadFirst // 1
29 | type LA = spreadLast // 3
30 |
31 | type FS = spreadFirstChar // 1
32 | type LS = spreadRestChar // 23
33 |
34 | type FN = spreadFirstChar // never
35 |
36 | ```
37 |
38 | [Go Demo](https://www.typescriptlang.org/play?#code/C4TwDgpgBAzmBOECGATAYgS3jYAeAKgHxQC8U+UEAHsBAHYoxQDaGdAZhPFJtsADRQAdCLaduAJQg4AulAD8PLDigAuKHQgA3LgG4AUPtCRYCZCgAySHAWJkK1WgybMRQsVyV9BH7ldkKUP7AahraeobG0HCIqLw4AMIAFkjwtqTklDT0jFAABgAkAN6+XjgAvsWlUhV5ivEh6po68AZG4NFmqDXAyanp9llOuYUlHJ4NlWPiUD3ldbPSjWEtbVFQAILw3GTMAIyCAEyCAMwy7SYAysA7UADke4cndxfQAHIArgC2GY8nkR0eBsMjFzA1cFt4IRXkFgWRQahghDttCYWhLiCuuhlL0UmlrlCYRYMfCsT0+vibqj1mg3pjYti+BTcJ8vtCgA)
39 |
40 | ### 游乐场
41 |
42 |
43 |
44 |
47 |
48 | ### 参考答案
49 |
50 | ```ts
51 | // answer
52 | ```
53 |
54 | ## 参考资料
55 |
56 |
57 |
--------------------------------------------------------------------------------
/docs/zh/type-assertion/README.md:
--------------------------------------------------------------------------------
1 | ## 定义
2 |
3 | 有时候你会比 `Typescript` 更了解你的值的类型, `Typescript` 允许你使用你想要的方式分析并覆盖它, 这种机制被称为 **「类型断言」**。
4 |
5 | ## 使用
6 |
7 | 类型断言有 **两种形式**:
8 |
9 | ### as
10 |
11 | ```ts
12 | const someValue: any = "this is a string";
13 |
14 | const strLength: number = (someValue as string).length;
15 | ```
16 |
17 | ### <> 尖括号
18 |
19 | ```ts
20 | const someValue: any = "this is a string";
21 |
22 | const strLength: number = (someValue).length;
23 | ```
24 |
25 | **Note:** 当你在 **`.jsx`** `or` **`.tsx`** 中使用 **尖括号** 的方式进行类型断言时, 会造成 **语言歧义**, 为了保持一致性, 推荐使用 `as` 语法来进行 **类型断言**。[相关体验](https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgApQPY2AGxQbwCgBIEOAWwgC5kBnMKUAcwG4S4nrkQBXcgI2jIAPnQbM2AX0KEEGEPWRweYABYYoyALzIAPOiy4IAPnyS2hZWo0A6MpW3IA5ACU4oAIwAmAAxPCQA)
26 |
27 | ## 双重断言
28 |
29 | 原理: 任何类型都可以被断言为 `any`, 而 `any` 可以被断言为任何类型。
30 |
31 | ```ts
32 | interface Person {
33 | name: string;
34 | }
35 |
36 | const mine = 'Rain120';
37 |
38 | ((age as any) as Person).name;
39 |
40 | ```
41 |
42 | **Note:** 双重断言极具破坏性, 而且它很可能会导致运行时错误, 慎用 !!!
43 |
44 | ## ! 后缀类型断言
45 |
46 | 我们知道 `Nullable` 类型实质上是 [**联合类型**](../advanced-types/union-types/README.md), 那么同样面临类型缩窄的问题。对此, `TypeScript` 也提供了符合直觉的类型保护。
47 |
48 | 自动类型保护无法处理的场景可以通过 `!` 后缀来去除 `Nullable`部分, 即 `null | undefined`。
49 |
50 | ```ts
51 | interface Profile {
52 | name: string;
53 | age?: number | string;
54 | }
55 | function getParentInfo(profile: Profile): number | string {
56 | return profile!.age!;
57 | }
58 | ```
59 |
60 | 更多操作符相关, 请到 [Here](../operator/README.md)
61 |
62 | ## 类型断言 与 类型转换
63 |
64 | 在计算机科学中, **[类型转换 (type conversion)](https://zh.wikipedia.org/zh-cn/%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2)** 是指将数据从一种类型 **转换成** 另一种类型的过程。所以 **类型转换** 是在 **运行时** 转换的, 而 **类型断言** 只是一个编译时的语法, 为编译器提供关于如何分析代码的方法。
65 |
66 | 若要进行类型转换, 需要直接调用类型转换的方法:
67 | ```ts
68 | Boolean();
69 |
70 | String();
71 |
72 | parseInt();
73 |
74 | // etc...
75 | ```
76 |
77 | ## 断言判断
78 |
79 | - **C类型** 是 **P类型** 的 **子类型**
80 |
81 | - **P类型** 是 **C类型** 的 **子类型**
82 |
83 | **C类型** 能被断言为 **P类型**。
84 |
85 | ## 快来耍耍啊
86 |
87 | ### 🌰🌰
88 |
89 |
90 |
91 | 请解决👇👇👇报错
92 |
93 | ```ts
94 | interface Profile {
95 | name: string;
96 | age: number | string;
97 | }
98 |
99 | const author = {};
100 |
101 | // Property 'name' does not exist on type '{}'.(2339)
102 | author.name = 'Rain120';
103 |
104 | ```
105 |
106 | ### 游乐场
107 |
108 |
109 |
110 |
113 |
114 | ### 参考答案
115 |
116 | ```ts
117 |
118 | interface Profile {
119 | name: string;
120 | age: number | string;
121 | }
122 |
123 | const author = {} as Profile;
124 |
125 | // const author = {};
126 |
127 | author.name = 'Rain120';
128 |
129 | ```
130 |
131 | ## 参考资料
132 |
133 | [Handbook - type-assertion](https://www.typescriptlang.org/docs/handbook/basic-types.html#type-assertions)
134 |
135 | [深入理解 Typescript](https://jkchao.github.io/typescript-book-chinese/typings/typeAssertion.html)
136 |
137 | [Typescript - type-assertion](https://ts.xcatliu.com/basics/type-assertion.html)
138 |
--------------------------------------------------------------------------------
/docs/zh/utility-types/README.md:
--------------------------------------------------------------------------------
1 | ## 定义
2 |
3 | `Typescript` 提供了几种 **实用工具类型**, 方便进行常见的类型转换。这些**实用工具类型**在全局范围内都可以使用。
4 |
5 | ## 实用工具类型
6 |
7 | 变量 `K`, `T`, `V` 详见[常见的一些泛型变量含义](../generics/#常见的一些泛型变量含义)
8 |
9 | ### `Partial`
10 |
11 | [Typescript 2.1 新增工具方法](https://devblogs.microsoft.com/typescript/announcing-typescript-2-1-2/)
12 |
13 | #### 定义
14 |
15 | 构造一个类型 `T`, 将类型 `T`的所有属性设置为 **可选属性**。该工具类方法将返回一个表示输入类型 `(T)` 的所有自己的类型。
16 |
17 | #### 使用
18 |
19 | ```ts
20 | interface Todo {
21 | title: string;
22 | description: string;
23 | }
24 |
25 | function updateTodo(todo: Todo, fieldsToUpdate: Partial) {
26 | return { ...todo, ...fieldsToUpdate };
27 | }
28 |
29 | const todo1 = {
30 | title: 'organize desk',
31 | description: 'clear clutter',
32 | };
33 |
34 | const todo2 = updateTodo(todo1, {
35 | description: 'throw out trash',
36 | });
37 |
38 | ```
39 |
40 | #### 源码实现
41 |
42 | ```ts
43 | type Partial = {
44 | [P in keyof T]?: T[P];
45 | }
46 |
47 | ```
48 |
49 | [直接体验](https://www.typescriptlang.org/play/#code/PTAEAUEMCcBcEtIBsBQL4DtYFNoDNIBjbUAFQHsATc0AbxQEgFYlsAuUAZ1mkwHMA3I0rZOhXgAcE5DB268MglAF80eAK4ZC0jKHUTKkHBWoAKWFXIcT5ADSg88bEkqcKAVQNH2EGAmQAPDYAfACUdIzQ2LDq0Lq0oAB0yRbU9smJjs6uHl44oMpCqiiEMtygqeQAjKAAvBFM8Cw+AOTk0HyQGPAAXiQinADWLbbCouLwUvAyHC2ErDCg8+qwONAjKkIlZbAVlgBMdXp52DbmllX29AwDE1MzoC2wABbQ5ADuoOQrFdCQnM8NspQgIgA)
50 |
51 | ### `Readonly`
52 |
53 | [Typescript 2.1 新增工具方法](https://devblogs.microsoft.com/typescript/announcing-typescript-2-1-2/)
54 |
55 | #### 定义
56 |
57 | 构造一个所有属性都设置为 **只读** 属性的类型 `T`, 这意味着 **无法** 再次对所有构造类型的属性进行 **赋值**。
58 |
59 | #### 使用
60 |
61 | ```ts
62 | interface Properties {
63 | cute: boolean;
64 | handsome: boolean;
65 | }
66 |
67 | let mine: Readonly = {
68 | cute: true,
69 | handsome: true,
70 | }
71 |
72 | mine.handsome = false;
73 | // Cannot assign to 'handsome' because it is a read-only property.(2540)
74 |
75 | ```
76 |
77 | 该工具对于表示在运行时会失败的赋值表达式很有用, 例如 [`Object freeze`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze)
78 |
79 | ```ts
80 | function freeze(obj: T): Readonly;
81 |
82 | ```
83 |
84 | #### 源码实现
85 |
86 | ```ts
87 | type Readonly = {
88 | readonly [P in keyof T]: T[P];
89 | }
90 | ```
91 |
92 | [直接体验](https://www.typescriptlang.org/play/?ssl=20&ssc=1&pln=1&pc=1#code/PTAECUFMEMBMHsB2AbAngKHQS0QF0gE4Bm0AxpKAAoHwAOhuWkAzqAN7oCQpArvgFygARvHjIYiANxcAFtESxm8ALaRBIsROkBfTONyhlONRBgIUqADzU6DJswB8oALzsuvAaFwEekADSy8ooqJt6+AbroRoiQAHRyCkqqLqAkyMyQkkA)
93 |
94 | ### `Record`
95 |
96 | [Typescript 2.1 新增工具方法](https://devblogs.microsoft.com/typescript/announcing-typescript-2-1-2/)
97 |
98 | #### 定义
99 |
100 | 构造一个属性为 `K` 类型, 属性值为 `T` 类型的类型。可用于将一个类型的属性 **映射到** 另一个类型中。
101 |
102 | #### 使用
103 |
104 | ```ts
105 | // Record
106 | interface Page {
107 | title?: string | undefined;
108 | content?: string | undefined;
109 | }
110 |
111 | type PageType = 'home' | 'about' | 'contact';
112 |
113 | const site: Record = {
114 | home: {
115 | content: 'home'
116 | },
117 | about: {
118 | title: 'about',
119 | content: 'about'
120 | },
121 | contact: {
122 | title: 'contact',
123 | // Error: Type '{ title: string; name: string; }' is not assignable to type 'Page'.
124 | // Object literal may only specify known properties,
125 | // and 'name' does not exist in type 'Page'.
126 | name: 'Rain120'
127 | },
128 | }
129 |
130 | ```
131 |
132 | #### 源码实现
133 |
134 | ```ts
135 | type Record = {
136 | [P in K]: T;
137 | }
138 | ```
139 |
140 | [直接体验](https://www.typescriptlang.org/play?#code/PTAECUFMGMHsCcAmAoAlgOwC6XgMwIbSSgAK+A5sQN7ICQmqmANpAPwBcoAzpvBuaAA+oAK7pEkXBkiIA3HThZIWDt178ho8ZOlzkAX2TJMATwAOxMpQAq54gF5QAcgAWsALaQnmp-gBGsCKY3sJOipiEwfLIijzcjJCcUHBIADxWkLYWADSkFJAAfKCONLRunpyltOHKmJyuHl50+tl0-oF1oFUMzInO7UFOrbTVsEpY9QPBzcPhkZV09Iws9XPQwa2gW9tbIKBZxE5UoD0ranzo5LKg6PgV5-zX+t6oXDewmKD4XFyo5Ld+FgnWAnOzODJOAB0yB2Oz2AHk-AArGCfJgJeD4Jigdz4EygMZMfFcCzQVC4fEAa3QsAA7uhQGZ4LALPAGJAuJtYbswPhxM5bp5vIhYBz3p9IAAPV6fDCgizg-JQxaCvpOcD4DAARgATAAGJwzAxAA)
141 |
142 | ### `Pick`
143 |
144 | [Typescript 2.1 新增工具方法](https://devblogs.microsoft.com/typescript/announcing-typescript-2-1-2/)
145 |
146 | #### 定义
147 |
148 | 通过从类型 `T` **选取** 属性 `K` 的集合来构造类型。
149 |
150 | #### 使用
151 |
152 | ```ts
153 | interface Todo {
154 | title: string;
155 | description: string;
156 | isCompleted: boolean;
157 | }
158 |
159 | type TodoWithDay = Pick
160 |
161 | const plan: TodoWithDay = {
162 | title: 'Writing for Typescript Guide',
163 | isCompleted: true
164 | }
165 |
166 | ```
167 |
168 | #### 源码实现
169 |
170 | ```ts
171 | type Pick = {
172 | [P in K]: T[P];
173 | }
174 | ```
175 |
176 | [直接体验](https://www.typescriptlang.org/play/?ssl=1&ssc=1&pln=15&pc=1#code/PTAEAUEsGMGsCh6QHYBcCmAnAZgQ2uqACoD2AJiaAN7yh2iqSoA26AXKAM6qYoDmAblr0y6TtF4AHRiWQduvZIOF1InAMIkAtpNYYyHAEYkSrXMiEBfRKgCekwqQoB1JgAsAIrlugAvBBhYAB4nEgAaUAByRhZ0SNAAHyi1TR09dDJIgD5EaFluUF1zDlDXVE9vP2oVBiZWDkjnXkYlUGwSTGJ7MQlIaVAAcQBXSFFIsJqU7V10fQ4eIfR4ayA)
177 |
178 | ### `Omit`
179 |
180 | [Typescript 3.5 新增工具方法](https://devblogs.microsoft.com/typescript/announcing-typescript-3-5/)
181 |
182 | #### 定义
183 |
184 | 通过从 类型 `T` 中 **选取** 所有属性, 然后 **删除** 传入的属性 `K` 来构造新类型。
185 |
186 | #### 使用
187 |
188 | ```ts
189 | interface Todo {
190 | title: string;
191 | description: string;
192 | isCompleted: boolean;
193 | }
194 |
195 | type TodoWithDay = Omit
196 |
197 | const plan: TodoWithDay = {
198 | title: 'Writing for Typescript Guide',
199 | isCompleted: true
200 | }
201 | ```
202 |
203 | #### 源码实现
204 |
205 | ```ts
206 | type Omit = Pick>
207 | ```
208 |
209 | [直接体验](https://www.typescriptlang.org/play/?ssl=9&ssc=32&pln=9&pc=43#code/PTAEHkFsEsBcCh7QHawKYCcBmBDAxmqACoD2AJiaAN7yh2ixwA2aAXKAM6wYoDmA3LXpk0HPDwAOjEsnZceyAULrQOAYRKQJLdGXYAjEiRY5kggL6JYATwmFSFAOpwAFgBEc10AF4IMWAA8DiQANKAA5CJiktLI4QB8iHgyXKDapuzBzrDunj7UygzMbBGOPIyKoFgkGMS2ouLQUqAA4gCu0CLhIYWqGlo6aHoMGG1o8JZAA)
210 |
211 | ### `Exclude`
212 |
213 | [Typescript 2.8 新增工具方法](https://devblogs.microsoft.com/typescript/announcing-typescript-2-8-2/)
214 |
215 | #### 定义
216 |
217 | 通过从类型 `T` 中 **剔除** 可赋值给 `U` 的属性来构造一个新类型。
218 |
219 | #### 使用
220 |
221 | ```ts
222 | type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"
223 |
224 | type T1 = Exclude<"a" | "b" | "c", "a" | "b">; // "c"
225 |
226 | type T2 = Exclude void), Function>; // string | number
227 |
228 | ```
229 |
230 | #### 源码实现
231 |
232 | ```ts
233 | type Exclude = T extends U ? never : T;
234 | ```
235 |
236 | [直接体验](https://www.typescriptlang.org/play/?ssl=1&ssc=4&pln=1&pc=15#code/PTAEFEA8GMBsFcAmBTAUKgLgTwA7NACoAMoAvBDAigDwBEAhraAD6i0BGTrt0tANG0YA+ANyhQINpxZte6bHkIBGMhThJkdRjI5dZ-QXt2jxknrXm58BAEyqo6mgGcMAJwCWAOwDmMz-ABbdmRXGQAKMIBKMiFQADcAe3dESIEAMXhPaAx3BM8TCTAXDx8-QODXVCA)
237 |
238 | ### `Extract`
239 |
240 | [Typescript 2.8 新增工具方法](https://devblogs.microsoft.com/typescript/announcing-typescript-2-8-2/)
241 |
242 | #### 定义
243 |
244 | 通过从类型 `T` 中 **挑选** 可赋值给 `U` 的属性来构造一个新类型。
245 |
246 | #### 使用
247 |
248 | ```ts
249 | type T0 = Extract<'a' | 'b', 'a'> // 'a'
250 |
251 | type T1 = Extract<'a' | 'b' | (() => void), Function> // () => void
252 | ```
253 |
254 | #### 源码实现
255 |
256 | ```ts
257 | type Extract = T extends U ? T : never;
258 | ```
259 |
260 | [直接体验](https://www.typescriptlang.org/play/?ssl=1&ssc=4&pln=1&pc=11#code/PTAEFEA8BcCcEMDG0BQLoE8AOBTUAVABlAF4IYFkAeAcnhtAB9QaAjGgGhfoD5QRuNNJlwEAjKXJwk0WvSYt2CgBTKAlKT4A3APYBLACZquAMQCuAO2R6dFvgPWbQuw0A)
261 |
262 | ### `NonNullable`
263 |
264 | [Typescript 2.8 新增工具方法](https://devblogs.microsoft.com/typescript/announcing-typescript-2-8-2/)
265 |
266 | #### 定义
267 |
268 | #### 使用
269 |
270 | ```ts
271 | // NonNullable
272 |
273 | type T0 = NonNullable<'a' | null> // 'a'
274 |
275 | type T1 = NonNullable<'a' | null | undefined> // 'a'
276 | ```
277 |
278 | #### 源码实现
279 |
280 | ```ts
281 | type NonNullable = T extends null | undefined ? never : T;
282 | ```
283 |
284 | [直接体验](https://www.typescriptlang.org/play/?ssl=1&ssc=4&pln=1&pc=15#code/PTAEDkHsDtwVwDYIIYCMEFMBQWAuBPABw1ABUAGUAXghniTUwB4BnXAJwEtoBzUAH1DQ4AW1QZ2A0HGgATDADNuGWQD4A3KFAhQbLrynCxEnAWJkAjNVqxEKdBlYduPANoBdQ3akz5S6CoaWjp6Lh5AA)
285 |
286 |
287 | ### `Parameters`
288 |
289 | #### 定义
290 |
291 | 构造一个关于函数类型 `T` 的 **参数类型** 的元组类型。请到 [#26019](https://github.com/Microsoft/TypeScript/issues/26019)
292 |
293 | #### 使用
294 |
295 | ```ts
296 | declare function f1(arg: { a: number, b: string }): void
297 |
298 | type T0 = Parameters<() => string>; // []
299 |
300 | type T1 = Parameters<(s: string) => void>; // [string]
301 |
302 | type T2 = Parameters<((arg: T) => T)>; // [unknown]
303 |
304 | type T4 = Parameters; // [{ a: number, b: string }]
305 |
306 | type T5 = Parameters; // unknown[]
307 |
308 | type T6 = Parameters; // never
309 |
310 | type T7 = Parameters; // Error
311 |
312 | type T8 = Parameters; // Error
313 | ```
314 |
315 | #### 源码实现
316 |
317 | ```ts
318 | type Parameters = {
319 | T extends (...args: infer P) => any ? P : never
320 | }
321 | ```
322 |
323 | [直接体验](https://www.typescriptlang.org/play/?ssl=3&ssc=1&pln=19&pc=42#code/PTAEAUEMCdIWwKYBcHQM4CgMBMEGMAbGBUAMwFcA7PJASwHtKyBGAChgHMAuUAb1Eg9K5OACNUAGlCieaJNFqUOoAL4BKHgDd6tbFiQBPAA4kAKgAZQAXggx4yVGgA8rNdYB8oOQqXuA3KCgIKAA2gC6+sZmzNa2sIgo6C5osvKKHG5Wntq6-oHBId7pERiGJqCmAEyxUPEOSaxOpu7s0NwVmZ6manlBYCFUANaU9ADulCVlZgAsNXYJjk5T9KQsvQX8gqDCYpLSqT7KKpNRFQCsc3WJzpCUButgQyPj4ZHlpgBsl-bXTpQImlQD22ANQbzMAHZvgskkVfAE+qAAKLQaD0aDgioADmh9WcADEqDQGJRgSi0dAgA)
324 |
325 |
326 | ### `ConstructorParameters`
327 |
328 | #### 定义
329 |
330 | 通过 `ConstructorParameters` 类型, 我们可以 **提取** 构造函数类型的 **所有参数类型**。 它会生成构造函数所具有的所有参数类型的元组类型(如果 `T` 不是函数, 则不返回)。
331 |
332 | #### 使用
333 |
334 | ```ts
335 | type T0 = ConstructorParameters; // [(string | undefined)?]
336 |
337 | type T1 = ConstructorParameters; // string[]
338 |
339 | type T2 = ConstructorParameters; // [string, (string | undefined)?]
340 | ```
341 |
342 | #### 源码实现
343 |
344 | ```ts
345 | type ConstructorParameters = {
346 | T extends new (...args: infer P) => any ? P : never
347 | }
348 | ```
349 |
350 | [直接体验](https://www.typescriptlang.org/play/?ssl=3&ssc=1&pln=7&pc=88#code/PTAEGEHsDsGcBcBOBXAxvSiAKBDROBbAU3iMVgCgL4BPAByNABUAGUAXghgRXU13zFS5ADwBRRIkxQ4SNBkQA+ANyhQIUAG0AFDwCW0AOagAPqGTQAJkQBmBopYCUAfgC6VWg2YBGDl1m8CgKEJGSwIgBiFuh6MDI88pgqahr6Rpru1PSMTABMfvFyfNh4IcLhAEpEhmIAHnSFgUmq6mCaaYYANKC6SAbGZhbWdtAOLq5AA)
351 |
352 | ### `ReturnType`
353 |
354 | [Typescript 2.8 新增工具方法](https://devblogs.microsoft.com/typescript/announcing-typescript-2-8-2/)
355 |
356 | #### 定义
357 |
358 | 构造一个由函数 `T` 的返回类型组成的新类型。
359 |
360 | #### 使用
361 |
362 | ```ts
363 | declare function f1(): { a: number, b: string }
364 |
365 | type T0 = ReturnType<() => string>; // string
366 |
367 | type T1 = ReturnType<(s: string) => void>; // void
368 |
369 | type T2 = ReturnType<(() => T)>; // {}
370 |
371 | type T3 = ReturnType<(() => T)>; // number[]
372 |
373 | type T4 = ReturnType; // { a: number, b: string }
374 |
375 | type T5 = ReturnType; // any
376 |
377 | type T6 = ReturnType; // any
378 |
379 | type T7 = ReturnType; // Error
380 |
381 | type T8 = ReturnType; // Error
382 | ```
383 |
384 | #### 源码实现
385 |
386 | ```ts
387 | type ReturnType<
388 | T extends (...args: any[]) => any
389 | > = T extends (...ages: any[]) => infer R ? R : any;
390 | ```
391 |
392 | [直接体验](https://www.typescriptlang.org/play/?ssl=1&ssc=4&pln=1&pc=15#code/PTAECUFMBcFcCcB2AVAngB0gKCwE0gMYA2AhvJKAGayIHQCWA9olQIwAUAlAFygDeoEr0SwAtgCNI8ADShxvAM7R49RAHNQAXyzQMFZAAZQAXggwEKPQB4uJgHyglK9XYDcoUCEfLVanXtBkVhMzOCQ0TBsFRR91TntQADdGelw3Dy9k1P9MQIAmEKgwy0j2K2Q7W2MHZE50zzA+bV1c5ABmQvNw6zLkUEgAD2hIRFwFUABVWQn+oZGx0BEJKQBtAF1K+OrAuvcGxbFJeHWc-QAWTuKIyCsWyEZKNnqvASED5Zk5GOcNZoDkACslws1ysJEQqGeYHBqFOgQAbMDupFEJBElIoYIIXDkAB2JElG5OXyYgCi8HgjHgOIAHATQQAxGh0JiIMkUqlAA)
393 |
394 | ### `InstanceType`
395 |
396 | [Typescript 2.8 新增工具方法](https://devblogs.microsoft.com/typescript/announcing-typescript-2-8-2/)
397 |
398 | #### 定义
399 |
400 | 构造y一个由构造函数 `T` 的 **实例类型** 组成的新类型。
401 |
402 | #### 使用
403 |
404 | ```ts
405 | class C {
406 | x = 0;
407 | y = 0;
408 | }
409 |
410 |
411 | type T0 = InstanceType; // C
412 |
413 | type T1 = InstanceType; // any
414 |
415 | type T2 = InstanceType; // any
416 |
417 | type T3 = InstanceType; // Error
418 |
419 | type T4 = InstanceType; // Error
420 | ```
421 |
422 | #### 源码实现
423 |
424 | ```ts
425 | type InstanceType<
426 | T extends new (...args: any[]) => any
427 | > = T extends new (...args: any[]) => infer R : R : any;
428 | ```
429 |
430 | [直接体验](https://www.typescriptlang.org/play/?ssl=17&ssc=39&pln=17&pc=44#code/PTAECUFMBcFcCcB2AVAngB0gKCwYwDYCGAzsaAMKgDeWodoAHqALygAMA3Lfai+1wF8cWaBkihkbPgElExaIUS5IaTAB5RmAPYAzCgD4OdEBRybxyAIwy5CpSrFrFqQ8bDOzYiQCYb8xcqqkGqIkABukPCuoCYeIl7IAMx+doGO8vAAlogA5tEmAKLw8FrwnpgSACwpAQ7qAGKwStCZWoj5YEUl8EA)
431 |
432 | ### `Required`
433 |
434 | [Typescript 2.8 rc 新增工具方法](https://devblogs.microsoft.com/typescript/announcing-typescript-2-8-rc/)
435 |
436 | #### 定义
437 |
438 | #### 使用
439 |
440 | ```ts
441 | interface Profile {
442 | name: string;
443 | age?: number;
444 | gender?: string;
445 | };
446 |
447 | // OK
448 | const profile: Profile = {
449 | name: 'Rain120',
450 | };
451 |
452 | // Type '{ name: string; }' is missing the following properties
453 | // from type 'Required': age, gender(2739)
454 | const ID_Card: Required = {
455 | name: 'Rain120',
456 | };
457 | ```
458 |
459 | #### 源码实现
460 |
461 | ```ts
462 | type Required = {
463 | [P in keyof T]-?: T[P];
464 | }
465 | ```
466 |
467 | 操作符相关问题请到 [Here](../operator/README.md)
468 |
469 | [直接体验](https://www.typescriptlang.org/play/#code/PTAECUFMEcFcEsBOkAmAoN8B2AXSiAzAQwGNJQAFRAewPgBtyBvNUN0LIgW0gC5QAzjkTYA5gG5W7IqMgB+fllhcARvkntQsrCnwLBwsZIC+ktCFAB5ANJoS1LENAAHGnUb8qtBuQC8oFk1OHn4AcnAibABGACYABlCAGjRTDDsHJwBJABEAfQBhIkQUfig4JFQAHi93SAA+UH8mUCk2YL5QcMisWITk0yA)
470 |
471 |
472 | ### `ThisParameterType`
473 |
474 | #### 定义
475 |
476 | 提取函数类型的 `this` 参数的类型, 如果函数类型没有 `this` 参数, 则 [未知](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html#new-unknown-top-type)。
477 |
478 | 注意: 仅当启用 `--strictFunctionTypes` 时, 此类型才能正常工作。 请到 [#32964](https://github.com/microsoft/TypeScript/issues/32964)
479 |
480 | #### 使用
481 |
482 | ```ts
483 | function toHex(this: Number) {
484 | return this.toString(16);
485 | }
486 |
487 | function numberToString(n: ThisParameterType) {
488 | return toHex.apply(n);
489 | }
490 | ```
491 |
492 | [直接体验](https://www.typescriptlang.org/play/?ssl=3&ssc=1&pln=9&pc=2#code/PTAEBUAsEsGcAUCGAnRBbApgFw88BPABwwCgSAzAVwDsBjLaAe2tC0YAkMAPACixlgAuUADlKaAEa4AlKADeJUEtDJslZC35wAdGwDKWZNGoBzHgEYAbNIDcJAL5kqdBs1DVxUvIwNHTPamEoOCRUTBw8IgwAHiwoxnJWDm4APlkFZRU1DSTOLm1EQkIAG3wA2wcgA)
493 |
494 |
495 | ### `OmitThisParameter`
496 |
497 | #### 定义
498 |
499 | 从函数类型中删除 `this` 参数。
500 |
501 | 注意: 仅当启用 `--strictFunctionTypes` 时, 此类型才能正常工作。请到 [#32964](https://github.com/microsoft/TypeScript/issues/32964)
502 |
503 | #### 使用
504 |
505 | ```ts
506 | function toHex(this: Number) {
507 | return this.toString(16);
508 | }
509 |
510 | // The return type of `bind` is already using `OmitThisParameter`, this is just for demonstration.
511 | const fiveToHex: OmitThisParameter = toHex.bind(5);
512 |
513 | console.log(fiveToHex());
514 | ```
515 |
516 | [直接体验](https://www.typescriptlang.org/play/?ssl=8&ssc=18&pln=8&pc=35#code/PTAEHkFsEsBcBUAW0DOAFAhgJw5AprHlgFDEBmArgHYDGs0A9laLAwBJ4AeAFLMigC5QAOQqQARkQCUoAN7FQi0FgIUszPqgB0rAMqws0KgHNuARgBsUgNzEAvqRCgkeZavUsAngAdXDMqAABuJGACaBoKigGAA2KhihnqAUKEbGQVBwSKiYOPiEWIEANCz8kSigAFYpsKBkDFigoXiQTCgGGPRMWsQ0bbVk0ABuePDsXEKZCPy5uAREADywPnj+LOOcAHygALzrHJxaIVSh3ACsNqR9VCgMMXhaMQymgyNjB9xSNkA)
517 |
518 |
519 | ### `ThisType`
520 |
521 | #### 定义
522 |
523 | 该工具 **不会返回转换后** 的类型。 相反, 它是一个用作上下文类型中键入 `this` 类型的标记。 注意, 必须启用 `–noImplicitThis` 标志才能使用此工具。
524 |
525 | #### 使用
526 |
527 | ```ts
528 | // Compile with --noImplicitThis
529 |
530 | type ObjectDescriptor = {
531 | data?: D;
532 | methods?: M & ThisType; // Type of 'this' in methods is D & M
533 | }
534 |
535 | function makeObject(desc: ObjectDescriptor): D & M {
536 | let data: object = desc.data || {};
537 | let methods: object = desc.methods || {};
538 | return { ...data, ...methods } as D & M;
539 | }
540 |
541 | let obj = makeObject({
542 | data: { x: 0, y: 0 },
543 | methods: {
544 | moveBy(dx: number, dy: number) {
545 | this.x += dx; // Strongly typed this
546 | this.y += dy; // Strongly typed this
547 | }
548 | }
549 | });
550 |
551 | obj.x = 10;
552 | obj.y = 20;
553 | obj.moveBy(5, 5);
554 |
555 | ```
556 |
557 | - 在上面的示例中, `makeObject` 的参数中的 `methods` 对象具有包含 `ThisType` 的上下文类型; 因此, 在 `methods` 对象内的方法中, 方法的 `this` 类型为 `{x: number, y: number}&{moveBy (dx: number, dy: number) : number}`。 请注意 `methods` 属性的类型是如何同时成为方法中 `this` 类型的推断目标和来源的。
558 | - `ThisType` 标记接口仅仅是在 `lib.d.ts` 中声明的一个空接口。 除了在对象字面量的上下文类型中被识别外, 该接口的作用类似于任何空接口。
559 |
560 | [直接体验](https://www.typescriptlang.org/play/#code/PTAEBUAsEsGdwJ4AcCmAoNJQGED2BbJaAGxVAHdoAXSUAWjoDtcBJQ46AY2qjgyuRkA8gCMAVik5UAIilicATtCRVcCgDzSANKACyAPlABeUAG80oS6AAmAQyq2A-AC5Q0gNwWr+FDVzXYFz1QADIIGHhBTVC9fXdLLERUUFwAM1AAcho4DNBoRlAfPwC82DcY3TQAXwxUgFdGKWhcAvxbAGsUUQkpTR0DAAprOU5XbskZEaUVNT7YgEpXaQqzL0tSKht7W1dccQnjGxGAOjsHUAAfC7MqzytQDcLfSH9YXf2pQ+H5Y6KXkquNzuVgUvjqCgKplAxxhZ1sOhhv2er1AVVAtjKyzCuk8NTQjz2YkObU64ykA3M9zhrihAA9XAAGHQIRmorRrJ7FN6re73fC4ABuKAAQgghvTQIw6vgRCgFDprCzJdLZQp5jzeZrsrBjrTQABqEzWWnxUBYADKVAULQA5sQEKABKhrI6IhzNZZtccHYabAhTRarbb7Y7BC7te6rDV7jUqvNPGhCbrDgBGBmeJMOkwAJnTifEv0FIrFAFYdCX40A)
561 |
562 |
563 | ## 快来耍耍啊
564 |
565 | ### 🌰🌰
566 |
567 |
568 |
569 | ```
570 | // template
571 | ```
572 |
573 | ### 游乐场
574 |
575 |
576 |
577 |
580 |
581 | ### 参考答案
582 |
583 | ```ts
584 | // answer
585 | ```
586 |
587 | ## 参考资料
588 |
589 | [handbook - utility-types](https://www.typescriptlang.org/docs/handbook/utility-types.html)
590 |
591 | [handbook - mapped-types](https://www.typescriptlang.org/docs/handbook/advanced-types.html#mapped-types)
592 |
593 | [Microsoft TypeScript wiki Road map](https://github.com/Microsoft/TypeScript/wiki/Roadmap)
594 |
595 | [Microsoft TypeScript #21316 Conditional Types](https://github.com/Microsoft/TypeScript/pull/21316)
596 |
597 | [Microsoft TypeScript #21496 infer pull request](https://github.com/Microsoft/TypeScript/pull/21496)
598 |
599 | [Conditional types in TypeScript](https://artsy.github.io/blog/2018/11/21/conditional-types-in-typescript/)
600 |
--------------------------------------------------------------------------------
/docs/zh/utility-types/custom-utility-types/README.md:
--------------------------------------------------------------------------------
1 | ## 定义
2 |
3 | Typescript 提供的实用工具类型并不能完全满足我们的需求,很多时候,我们都需要自定义一些满足我们需求的工具类型。
4 |
5 | ### 集合的操作
6 |
7 | ### 交集
8 |
9 | **定义: 对于给定的两个集合,返回一个包含两个集合中共有元素的新集合。**
10 |
11 | 我们可以借助[Pick](https://rain120.github.io/typescript-guide/zh/utility-types/#pick-t-k) 和 [Extract](https://rain120.github.io/typescript-guide/zh/utility-types/#extract-t-u)来实现。
12 |
13 | ```ts
14 | type Intersection = Pick<
15 | T,
16 | Extract & Extract
17 | >
18 | ```
19 |
20 | [直接体验](https://www.typescriptlang.org/play?#code/C4TwDgpgBACgjFAvFA3lAdgQwLYQFxQDOwATgJboDmANFJpfkaRZVAL4BQoksATEqgw5GxclVr1G6AK7YARhBK0G6ACaKColuw5dw0AJLpgiwhADGwMgHt0AHg5QnUACpQIADxNrCUa3IArC2BqR2cAVXcvCB8-QOCOAD4BGDJzAGsHZ1dQ7IBRLxJMSzt0iBBrADMcqDKK6vDkgDIoAtJi4FLyqqhw2jqel0Sk3W5oGAEjExIzSxt7eFoYXkSgA)
21 |
22 | ### 并集
23 |
24 | **定义: 对于给定的两个集合,返回一个包含两个集合中所有元素的新集合。**
25 |
26 | ```ts
27 | // 合并交叉类型
28 | type Compute = T extends Function
29 | ? T
30 | : { [K in keyof T]: T[K] }
31 |
32 | // P1: { name: string, age: string }
33 | // P2: { name: string, gender: string }
34 | // Res => { name: string, age: string } & { gender: string }
35 | // => { name: string, age: string, gender: string }
36 | type Merge = Compute<
37 | T & Omit
38 | >
39 | ```
40 |
41 | #### demo
42 |
43 | ```ts
44 | type P1 = {
45 | name: string,
46 | age: string
47 | }
48 | type P2 = {
49 | name: string,
50 | age: number,
51 | gender: string
52 | }
53 |
54 | type Intersection<
55 | T extends object,
56 | U extends object
57 | > = Pick<
58 | T,
59 | Extract & Extract
60 | >
61 |
62 | // { name: string, age: string }
63 | type P = Intersection
64 | ```
65 |
66 | #### demo
67 |
68 | ```ts
69 | type P1 = {
70 | name: string,
71 | age: string
72 | }
73 | type P2 = {
74 | name: string,
75 | age: number,
76 | gender: string
77 | }
78 |
79 | type Compute = T extends Function ? T : {
80 | [K in keyof T]: T[K]
81 | }
82 |
83 | type Merge = Compute<
84 | T & Omit
85 | >
86 |
87 | // { name: string; age: string; gender: string; }
88 | type P = Merge
89 | ```
90 |
91 | [直接体验](https://www.typescriptlang.org/play?#code/C4TwDgpgBACgjFAvFA3lAdgQwLYQFxQDOwATgJboDmANFJpfkaRZVAL4BQoksATEqgw5GxclVr1G6AK7YARhBK0G6ACaKColuw5dw0AMIB7bGGnAIAHgAqUCAA8LawnXQgAfANsOnqlwDFpdABjYDIjdCgAfihbAhQOKCSoAG0AaSgKKABrCBAjADNYgF0Ca3Tijk49HgBZRQYbO0cIZygjOQArCFDaAFVm3xcO7tDPZGNTcytE5NsAMigAeWwyYEs+2lz8out3Dn2a6BgBepJG+FoYXn2gA)
92 |
93 | 这里合并之后会发现,age 属性是使用前面属性的类型,这里如何解决呢?
94 |
95 | ### Overwrite
96 |
97 | ```ts
98 | type Overwrite<
99 | T extends object,
100 | U extends object,
101 | I = Diff & Intersection
102 | > = Pick
103 | ```
104 |
105 | #### demo
106 |
107 | ```ts
108 | type P1 = {
109 | name: string,
110 | age: string
111 | }
112 | type P2 = {
113 | name: string,
114 | age: number,
115 | gender: string
116 | }
117 |
118 | type Intersection<
119 | T extends object,
120 | U extends object
121 | > = Pick<
122 | T,
123 | Extract & Extract
124 | >
125 |
126 | type Diff<
127 | T extends object,
128 | U extends object
129 | > = Pick<
130 | T,
131 | Exclude
132 | >
133 |
134 | type Compute = T extends Function ? T : {
135 | [K in keyof T]: T[K]
136 | }
137 |
138 | type Merge = Compute<
139 | T & Omit
140 | >
141 |
142 | type Overwrite<
143 | T extends object,
144 | U extends object,
145 | I = Diff & Intersection
146 | > = Pick
147 |
148 | type P = Overwrite
149 | ```
150 |
151 | [直接体验](https://www.typescriptlang.org/play?#code/C4TwDgpgBACgjFAvFA3lAdgQwLYQFxQDOwATgJboDmANFJpfkaRZVAL4BQoksATEqgw5GxclVr1G6AK7YARhBK0G6ACaKColuw5dw0AJLpgiwhADGwMgHt0AHg5QnUACpQIADxNrCUa3IArC2BqR2cAVXcvCB8-QOCOAD4BGDJzAGsHZ1dQ7IBRLxJMSzt0iBBrADMcqDKK6vDkgDIoAtJi4FLyqqhw2jqel0Sk3W5oABEySsqs5zdPb1VffyDLXIioxeX4yySUtMywpxd1pwLzABtpdS76moGG4eG9HgBha2wwaRM7eejYzDoEDJZB-LZQABi0nQlhs6CgAH5XFACCgjlAANoAaSgFFq3WqLgAugQXNiiRxOC9oABZRQMX6bGJLOKrEK9JmxFbBEFQd6fb4QWbHKAtADy2DInT6+LuQxG1NgAjpJAZ8FoMF4zzGUDFADdFAB3cg-MJg5nbNnrSILC2s4LrAwCSbTX60RqiqBGEwkMyw2x2GXy3mpDJ2Az9Ale7X6XUwAT6o0moXqviJIA)
152 |
153 | ### 差集
154 |
155 | **定义: 对于给定的两个集合,返回一个包含所有存在于第一个且不存在于第二个集合的元素的新集合。**
156 |
157 | ```ts
158 | type Diff = Pick<
159 | T,
160 | Exclude
161 | >
162 | ```
163 |
164 | #### demo
165 |
166 | ```ts
167 | type P1 = {
168 | name: string,
169 | age: string
170 | }
171 | type P2 = {
172 | name: string,
173 | age: number,
174 | gender: string
175 | }
176 |
177 | type Diff<
178 | T extends object,
179 | U extends object
180 | > = Pick<
181 | T,
182 | Exclude
183 | >
184 |
185 | // { gender: string }
186 | type P = Diff
187 | ```
188 |
189 | [直接体验](https://www.typescriptlang.org/play?#code/C4TwDgpgBACgjFAvFA3lAdgQwLYQFxQDOwATgJboDmANFJpfkaRZVAL4BQoksATEqgw5GxclVr1G6AK7YARhBK0G6ACaKColuw5dw0ACJkAZsYA8HKFagAVKBAAewCGsJQA9nIBWEAMbBqS2sAVXsnF1U3Tx9-DgA+ARgyXwBrC2tbQIyAUQdfABtpdTMUiBB3Y0yoUvLK4Lj43W5oGAEjUzMYXlp4OKA)
190 |
191 | ## 快来耍耍啊
192 |
193 | ### 🌰🌰
194 |
195 |
196 |
197 | ```
198 | // template
199 | ```
200 |
201 | ### 游乐场
202 |
203 |
204 |
205 |
208 |
209 | ### 参考答案
210 |
211 | ```ts
212 | // answer
213 | ```
214 |
215 | ## 参考资料
216 |
217 |
218 |
--------------------------------------------------------------------------------
/docs/zh/what-is-typescript/README.md:
--------------------------------------------------------------------------------
1 | ## 定义
2 |
3 | [TypeScript](https://www.typescriptlang.org/) 是一种由微软开发的自由和开源的编程语言。它是 `JavaScript` 的一个超集, 包含了 `JavaScript` 的所有元素, 可以载入 `JavaScript` 代码运行, 并扩展了 `JavaScript` 的语法, 而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。它可以编译成纯 `JavaScript` 。编译出来的 `JavaScript` 可以运行在任何浏览器上。`TypeScript `编译工具可以运行在任何服务器和任何系统上。 [TypeScript Github](https://github.com/Microsoft/TypeScript)
4 |
5 | ## Typescript 与 JavaScript 的区别
6 |
7 | | Typescript | Javascript |
8 | |---------|---------|
9 | |静态语言|动态语言|
10 | |一种面向对象的编程语言, 需要TypeScript编译器才能转换为JavaScript文件|一种脚本语言, 不需要编译器, 可以在浏览器上运行。|
11 | |强类型, 支持静态和动态类型|弱类型, 没有静态类型选项|
12 | |接口,重载等特性|不支持接口,同名函数会被最后定的覆盖|
13 |
14 | ## 为什么使用TypeScript
15 |
16 | `TypeScript` 有两个主要目标:
17 |
18 | - 提供 `JavaScript` 的可选类型系统。
19 |
20 | - 提供从将来的 `JavaScript` 版本到当前 `JavaScript` 引擎的计划功能
21 |
22 | 
23 |
24 | [npm 下载量](https://npm-stat.com/charts.html?package=typescript&from=2015-01-01)
25 |
26 | ### 为什么要向 JavaScript 添加类型
27 |
28 | 类型具有 **提高代码质量** 和 **可理解性** 的能力。大型团队(`Google`, `Microsoft`, `Facebook`)一直在得出这一结论。 特别:
29 |
30 | - 类型在进行重构时可以提高敏捷性。 对于编译器来说, **捕获错误** 比使事情在运行时失败更好。
31 |
32 | - 类型是您可以拥有的最佳文档形式之一。 函数签名是一个定理, 函数体是证明。
33 |
34 | 但是, 类型定义有时候不需要特别的正式。 `TypeScript` 会根据类型推导尽可能降低的我们定义类型的成本。
35 |
36 | ## 如何使用
37 |
38 | ### 安装
39 |
40 | ```sh
41 | npm install -g typescript
42 | ```
43 |
44 | ### 新建文件
45 | ```sh
46 | echo hello_world.ts > const gender: string = 'Female';
47 | ```
48 |
49 | ### 编译
50 | ```sh
51 | tsc hello_world.ts
52 | ```
53 |
54 | ## 直接尝试
55 |
56 | [TypeScript Playground](https://www.typescriptlang.org/play/index.html)
57 |
58 |
63 |
64 | ## 学习资料
65 |
66 | [《TypeScript Deep Dive》](https://basarat.gitbook.io/typescript/) 是一本很好的开源书, 从基础到深入, 很全面的阐述了 `TypeScript` 的各种魔法, 不管你是新手, 还是老鸟, 它都将适应你。此外, 它不同于 `TypeScript` 官方给出的文档(当然 `TypeScript` 给出的文档是很好的), 在此书中, 结合实际应用下的场景用例, 你将能更深入的理解 `TypeScript`。[中文版](https://jkchao.github.io/typescript-book-chinese/)
67 |
68 | [awesome-typescript](https://github.com/semlinker/awesome-typescript) 收集了很多 `Typescript` 的相关学习资料。
69 |
70 | ## 参考资料
71 |
72 | [TypeScript](https://www.typescriptlang.org/)
73 |
74 | [TypeScript Github](https://github.com/Microsoft/TypeScript)
75 |
76 | [typescript Announcing](https://devblogs.microsoft.com/typescript/)
77 |
78 | [Why Typescript](https://basarat.gitbook.io/typescript/getting-started/why-typescript)
79 |
80 | [TypeScript 入门教程](https://juejin.im/post/5edd8ad8f265da76fc45362c)
81 |
82 | [未来可期的 TypeScript](https://mp.weixin.qq.com/s?__biz=MzIxNjgwMDIzMA==&mid=2247485103&idx=1&sn=9063e21d824db34820e955967c5a8ea3&scene=21#wechat_redirect)
83 |
84 | [非官方中文版](http://s0www0typescriptlang0org.icopy.site/index.html)
85 |
86 | [type-challenges](https://github.com/type-challenges/type-challenges)
87 |
--------------------------------------------------------------------------------
/docs/zh/what-is-typescript/images/2020-ts-download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rain120/typescript-guide/90432f8d4e8b7b20a76d678886f7e1075c3ae6ff/docs/zh/what-is-typescript/images/2020-ts-download.png
--------------------------------------------------------------------------------
/how-to-write-docs.md:
--------------------------------------------------------------------------------
1 | ## 如何写文档?
2 |
3 | 文档的规范, 以及如何方便快捷的书写 ✍️ 文档
4 |
5 | ## 新建文件
6 |
7 | 在`docs/zh`中新建一个文件, 并新建一个 `README.md`的文件
8 |
9 | **请保证每一个文件夹都有一个 `README.md`文件**
10 |
11 | **手动创建**
12 |
13 | ```sh
14 | touch docs/zh/test/README.md
15 | ```
16 |
17 | **自动生成 `docs model`**
18 | ```sh
19 | npm run docs
20 | ```
21 |
22 | ```sh
23 | ? please input the docs model name: model
24 | ? please input the docs model alias name (default same as model name)?
25 | ? generator model path (etc: docs/zh/model) ? docs/zh
26 | ```
27 |
28 | `Eg: File Path`
29 |
30 | ```sh
31 | ├── guide
32 | │ └── README.md
33 | ├── how-to-config-docs
34 | │ └── README.md
35 | └── how-to-write-docs
36 | └── README.md
37 | ```
38 |
39 | ### Tips & FAQs 如何添加到子目录下
40 |
41 | #### Tips
42 |
43 | ```sh
44 | ? npm run docs
45 |
46 | ? please input the docs model name: tips-test
47 | ? please input the docs model alias name (default same as model name)? 测试新增 tips
48 | ? generator model path (etc: docs/zh/model) ? docs/zh/tips
49 | ```
50 |
51 | #### FAQs
52 |
53 | ```sh
54 | ? npm run docs
55 |
56 | ? please input the docs model name: faqs-test
57 | ? please input the docs model alias name (default same as model name)? 测试新增 faqs
58 | ? generator model path (etc: docs/zh/model) ? docs/zh/faqs
59 | ```
60 |
61 | ## 配置别名
62 |
63 | ### 简约配置方式
64 |
65 | 通过使用 [新建文件](#新建文件) 的脚本来动态配置 `alias`, 妈妈再也不用担心我找不到配置了。
66 |
67 | ## 图片
68 |
69 | `~@images`路径 `->` 根路径
70 |
71 | ```md
72 | 
73 | ```
74 |
75 | `Eg:`
76 |
77 | ```md
78 | 
79 | ```
80 |
81 | ## 导入代码块
82 |
83 | 你可以在文档中展示你的代码, 只需要使用下面方式即可
84 |
85 | ```md {highlight number}
86 | <<< @/filepath
87 | ```
88 |
89 | **Note:** `filepath`是你文档的路径
90 |
91 | `Eg:`
92 |
93 | ```md {1}
94 | <<< @/scripts/deploy.sh
95 | ```
96 |
97 | ## 数学公式
98 |
99 | 你可以在文档中使用 **`markdown`** 来书写一下数学公式
100 |
101 | ```md
102 | $$
103 | y=\begin{cases}
104 | -x,\quad x\leq 0 \\\\
105 | x,\quad x>0
106 | \end{cases}
107 | $$
108 | ```
109 |
110 | ## Badge 徽章
111 |
112 | - **Props:**
113 |
114 | - `text - string`
115 |
116 | - `type - string`, 可选值: `'tip' | 'warning' | 'error'`, 默认值是: `'tip'`
117 |
118 | - `vertical - string`, 可选值: `'top' | 'middle'`, 默认值是: `'top'`
119 |
120 | - **Usage:**
121 |
122 | 你可以在标题中, 使用这个组件来为某些 API 添加一些状态:
123 |
124 | ```md
125 | Badge
126 | ```
127 |
128 | ## 自定义容器
129 |
130 | ```md
131 | ::: tip
132 | This is a tip
133 | :::
134 |
135 | ::: warning
136 | This is a warning
137 | :::
138 |
139 | ::: danger
140 | This is a dangerous warning
141 | :::
142 | ```
143 |
144 | ## Emoji
145 |
146 | ```md
147 | :tada: :100:
148 | ```
149 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "typescript-guide",
3 | "author": "Rain120",
4 | "repository": {
5 | "type": "git",
6 | "url": "git+https://github.com/Rain120/typescript-guide.git"
7 | },
8 | "version": "1.0.0",
9 | "description": "Awesome code implementation for Javascript",
10 | "main": "index.js",
11 | "scripts": {
12 | "lint-staged": "lint-staged",
13 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add .",
14 | "plop": "./node_modules/.bin/plop",
15 | "docs": "npm run plop docs",
16 | "docs:dev": "vuepress dev docs",
17 | "docs:build": "vuepress build docs",
18 | "deploy": "bash ./scripts/deploy.sh",
19 | "remote": "bash ./scripts/remote.sh"
20 | },
21 | "keywords": [
22 | "docs",
23 | "vuepress",
24 | "template",
25 | "vuepress-docs",
26 | "docs-template",
27 | "typescript",
28 | "typescript-guide"
29 | ],
30 | "license": "MIT",
31 | "bugs": {
32 | "url": "https://github.com/Rain120/typescript-guide/issues"
33 | },
34 | "homepage": "https://github.com/Rain120/typescript-guide#readme",
35 | "lint-staged": {
36 | "{src}/**/**.ts": [
37 | "git add"
38 | ]
39 | },
40 | "husky": {
41 | "hooks": {
42 | "pre-commit": "npm run changelog && lint-staged",
43 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
44 | }
45 | },
46 | "dependencies": {
47 | "monaco-editor": "^0.20.0"
48 | },
49 | "devDependencies": {
50 | "@commitlint/cli": "^11.0.0",
51 | "@commitlint/config-conventional": "^11.0.0",
52 | "@vuepress/plugin-back-to-top": "^1.2.0",
53 | "@vuepress/plugin-blog": "^1.9.2",
54 | "@vuepress/plugin-google-analytics": "^1.2.0",
55 | "@vuepress/plugin-medium-zoom": "^1.5.2",
56 | "@vuepress/plugin-pwa": "^1.3.0",
57 | "conventional-changelog-cli": "^2.0.27",
58 | "husky": "^3.1.0",
59 | "lint-staged": "^9.5.0",
60 | "markdown-it-imsize": "^2.0.1",
61 | "markdown-it-katex": "^2.0.3",
62 | "markdown-it-task-lists": "^2.1.1",
63 | "moment": "^2.24.0",
64 | "monaco-editor-webpack-plugin": "^1.9.0",
65 | "plop": "^2.6.0",
66 | "vuepress": "^1.5.2",
67 | "vuepress-plugin-awesome-gitalk": "^0.0.4",
68 | "vuepress-plugin-container": "^2.1.4",
69 | "vuepress-plugin-mathjax": "^1.2.8"
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/plop-templates/README.md.hbs:
--------------------------------------------------------------------------------
1 | ## 定义
2 |
3 | ## 使用
4 |
5 | ## 快来耍耍啊
6 |
7 | ### 🌰🌰
8 |
9 |
10 |
11 | ```
12 | // template
13 | ```
14 |
15 | ### 游乐场
16 |
17 |
18 |
19 |
22 |
23 | ### 参考答案
24 |
25 | ```ts
26 | // answer
27 | ```
28 |
29 | ## 参考资料
30 |
31 |
32 |
--------------------------------------------------------------------------------
/plopfile.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: Rainy
3 | * @Date: 2020-03-04 17:43:25
4 | * @LastEditors: Rainy
5 | * @LastEditTime: 2020-08-06 19:34:34
6 | */
7 |
8 | const path = require('path');
9 | const fs = require('fs');
10 |
11 | const aliasPath = path.resolve('docs/.vuepress/utils/alias.json')
12 | const last = ['tips', 'faqs'];
13 |
14 | /**
15 | *
16 | * @param {string} key modal name
17 | * @param {string} value modal alias
18 | */
19 | function addAlias({ name, alias }) {
20 | const data = fs.readFileSync(aliasPath, 'utf-8');
21 | const content = JSON.parse(data);
22 | if (!alias) {
23 | alias = name;
24 | }
25 | if (!content[name]) {
26 | content[name] = alias;
27 | } else {
28 | throw new Error('The name is exist');
29 | }
30 |
31 | const value = {};
32 | Object.keys(content).forEach(name => {
33 | if (!last.includes(name)) {
34 | value[name] = content[name];
35 | }
36 | });
37 |
38 | last.forEach(name => {
39 | value[name] = content[name];
40 | });
41 |
42 | const file = JSON.stringify(value, null, 2);
43 |
44 | fs.writeFileSync(aliasPath, new Buffer(file))
45 | }
46 |
47 | module.exports = plop => {
48 | plop.setGenerator('docs', {
49 | description: 'Create zh docs',
50 | prompts: [
51 | {
52 | type: 'input',
53 | name: 'name',
54 | message: 'please input the docs model name: ',
55 | default: 'model'
56 | },
57 | {
58 | type: 'input',
59 | name: 'alias',
60 | message: 'please input the docs model alias name (default same as model name)?'
61 | },
62 | {
63 | type: 'input',
64 | name: 'path',
65 | message: 'generator model path (etc: docs/zh/model) ?',
66 | default: 'docs/zh'
67 | }
68 | ],
69 | actions: answer => {
70 | addAlias(answer);
71 | return [
72 | {
73 | type: 'add',
74 | path: '{{path}}/{{name}}/README.md',
75 | templateFile: 'plop-templates//README.md.hbs'
76 | }
77 | ];
78 | }
79 | });
80 | };
81 |
--------------------------------------------------------------------------------
/scripts/deploy.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | set -e
4 |
5 | npm run docs:build
6 |
7 | cd docs/.vuepress/dist
8 |
9 | git init
10 | git add -A
11 | git commit -m 'deploy vuepress docs gh-pages'
12 |
13 | git push -f git@github.com:Rain120/typescript-guide.git master:gh-pages
14 |
15 | cd -
16 |
--------------------------------------------------------------------------------
/scripts/remote.sh:
--------------------------------------------------------------------------------
1 | ###
2 | # @Author: Rainy
3 | # @Date: 2020-07-05 15:59:16
4 | # @LastEditors: Rainy
5 | # @LastEditTime: 2020-07-05 15:59:17
6 | ###
7 |
8 | #!/usr/bin/env sh
9 |
10 | # git@github.com:Rain120/vuepress-docs-template.git
11 |
12 | set -e
13 |
14 | if [[ -n "$1" ]];then
15 |
16 | git remote -v
17 |
18 | echo "Old Origin"
19 |
20 | git remote remove origin
21 |
22 | echo "Add origin $1"
23 |
24 | git remote add origin $1
25 |
26 | echo "New Origin"
27 | git remote -v
28 |
29 | else
30 |
31 | echo "Please add the Origin Address"
32 |
33 | fi
34 |
--------------------------------------------------------------------------------
/wechat-zhifubao-pay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rain120/typescript-guide/90432f8d4e8b7b20a76d678886f7e1075c3ae6ff/wechat-zhifubao-pay.png
--------------------------------------------------------------------------------