使用规范
- 尽量不使用断言
!
?
- 使用
unknown
而不是any
- 泛型在
interface
和type
同样实用 - 不要在模块中使用
namespace
- 回调函数不要有可选参数
类型
未指定类型且无法推测, 类型隐式为 any
object: {} = {}
, object['testKey']
的类型判断: 判断 'testKey'
是否属于 keyof typeof object
, 不属于的话 object
的类型为隐式any
as const
可转换数组类型为元组, 对象为枚举
条件类型 SomeType extends OtherType ? TrueType : FalseType
, infer
常用的针对多类型缩小范围
typeof
in
instanceof
-
parameterName is Type
, 文档看起来很有用?
模板文字类型
type PropEventSource<Type> = {
on<Key extends string & keyof Type>
(eventName: `${Key}Changed`, callback: (newValue: Type[Key]) => void ): void;
};
declare function makeWatchedObject<Type>(obj: Type): Type & PropEventSource<Type>;
const person = makeWatchedObject({
firstName: "Saoirse",
lastName: "Ronan",
age: 26
});
// (parameter) newName: string
person.on("firstNameChanged", newName => {
console.log(`new name is ${newName.toUpperCase()}`);
});
// (parameter) newAge: number
person.on("ageChanged", newAge => {
if (newAge < 0) {
console.warn("warning! negative age");
}
})
模块
顶层有 import
或 export
被视为模块, 反之为脚本, 脚本具有全局作用域.
export =
导出 CommonJS
和 AMD
模块, import = require()
导入
相对导入( \
, .\
, ..\
)不会被解析为环境模块声明, 非相对导入可以被解析为环境模块声明
import type
导入类型定义
模块解析策略
函数
如果函数不声明返回类型, 会根据 return
语句自动推断, 无 return
或 return
后面不带内容, 则为 void
void
代表返回值被忽略, 实际上仍然可以 return
任何值
参数名为 this
的参数会在编译时擦除, 仅校验 this
类型
类
派生类调用 this
前必须在构造函数首先执行 super
函数, super
实际上就是执行了父类的构造函数
implements
检查是否存在特定接口, 不检查类型, 不改变类
类型参数无法运用在静态成员
构造函数类型 new () => Class
构造函数参数如果有 public
, private
, protected
, readonly
修饰, 会调用 this.key = value
class Params {
constructor(
public a: number,
protected b: number,
private c: number,
readonly d: number,
e: number,
) {}
}
// 编译为:
class Params {
constructor(a, b, c, d, e) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
}
}
this is Type
, 文档看起来很有用?
类初始化
class Base {
name = "base";
constructor() {
console.log("My name is " + this.name);
}
}
class Derived extends Base {
name = "derived";
}
// Prints "base", not "derived"
const d = new Derived();
- 初始化基类字段
- 运行基类构造函数
- 初始化派生类字段
- 运行派生类构造函数
内置的类型函数
用法 | 注释 |
| - |
| - |
| - |
| 定义对象的属性类型为 |
| 从对象类型 |
| 与 |
| 联合类型 |
| 与 |
|
|
|
|
|
|
|
|
|
|
|
|
| 去除 |
| 非转换, 声明 |
| - |
| - |
| - |
| - |
装饰器
T: 静态成员的构造函数或实例对应类的原型, 成员名, 成员的属性描述符
R : 如果有返回值, 返回值作为成员的属性描述符
类型 | 参数 | 返回值 |
类装饰器 | 构造函数 | 如果有返回值, 返回值作为新的构造函数, 需要维护原型链 |
方法装饰器 | T | R |
存取装饰器 | T | R |
属性装饰器 | 静态成员的构造函数或实例对应类的原型, 成员名 | 文档说返回值被忽略, 实际不是, 参考 issue |
参数装饰器 | T | 参数的索引 |
tsconfig.json
项目配置
outDir
: ts编译文件输出到的文件夹路径
rootDir
: ts编译文件输出到文件夹时, 和输入文件结构相同, 指定 rootDir
为目录结构根节点
downlevelIteration
: 如果存在 Symbol.iterator
, 会在ES5环境中模仿ES6的迭代操作( for of
, ...
)
importHelpers
: 全局导入 tslib
, 确保 tslib
运行时可被引入
incremental
: 保存上一次编译时的项目图解
isolatedModules
: 防止其它编译器解析单个文件时产生错误(如导出类型)
lib
: 包含哪些内置的JS API定义
module
: 模块系统, node
项目使用 CommonJS
, 影响 moduleResolution
noEmit
: 禁止编译输出文件, 为了其它编译器能够处理TS文件
outFile
: 非模块文件将被输出到单个文件中, module
必须为 None
, System
或 AMD
plugins
: 编辑器中运行的语言服务插件 vscode参考
严格检查
strict
: 启用所有严格检查选项
模块解析
allowSyntheticDefaultImports
: 模拟 Babel
创建 default
导出, 可用 import React from "react";
代替 import * as React from "react";
baseUrl
: 非相对路径模块查找时的根目录
paths
: 相对于 baseUrl
的重映射
esModuleInterop
: 保证 import
导入 CommonJS/AMD/UMD 模块的兼容性
rootDirs
: 合并多个目录到一个虚拟目录, 相对路径的 import
可跨层级
typeRoots
: 声明文件路径
types
: 全局引入哪些声明
源地图
inlineSourceMap
: 与 sourceMap
互斥, 以行内注解的方式构建源地图
inlineSources
: 开启 sourceMap
或 inlineSourceMap
, 与 inlineSourceMap
表现相同
mapRoot
: 指定源地图位置
sourceRoot
: 指定源位置
Linter检查
noFallthroughCasesInSwitch
: switch
语句包含 break
或 return
noImplicitOverride
: 子类函数重载, 必须含关键字 override
noImplicitReturns
: 确保所有可能的返回值被检查
noPropertyAccessFromIndexSignature
: 确保 obj.key
和 obj["key"]
的形式匹配相应的类型声明
noUncheckedIndexedAccess
: 将 undefined
添加到类型中任何未声明的字段
noUnusedLocals
: 未使用的局部变量报错, _
开头的变量忽略检查
noUnusedParameters
: 未使用的函数参数报错
实验性
emitDecoratorMetadata
: 装饰器支持元数据
experimentalDecorators
: 装饰器支持
其它
allowUnreachableCode
: 允许不可能运行的代码
allowUnusedLabels
: 允许未使用的标签
assumeChangesOnlyAffectDirectDependencies
: 仅重新检查/重新构建直接导入变化模块的文件
charset
: 文件编码
declarationDir
: 声明文件输出目录
diagnostics
: 输出诊断信息用于调试
disableReferencedProjectLoad
: 仅在编辑器打开文件时载入相应项目
disableSizeLimit
: 移除内存上限
emitDeclarationOnly
: 仅输出声明文件
explainFiles
: 打印文件如何成为编译的一部分
extendedDiagnostics
: 性能诊断
forceConsistentCasingInFileNames
: 是否区分文件名大小写
generateCpuProfile
: 输出 v8 CPU 配置
listEmittedFiles
: 打印输出文件列表
listFiles
: 打印包含在编译中的文件列表, 建议使用 explainFiles
newLine
: 输出文件的EOL
noEmitHelpers
: 关闭输出辅助函数, 为了自定义辅助函数
noEmitOnError
: 报错不输出文件
noErrorTruncation
: 不截断报错信息
noStrictGenericChecks
: 移除严格的泛型检查
preserveConstEnums
: 不擦除 const enum
声明
resolveJsonModule
: 可解析 JSON 文件
skipDefaultLibCheck
: 跳过默认库的类型检查
skipLibCheck
: 跳过库的类型检查
traceResolution
: 输出每个已处理文件的解析过程
useDefineForClassFields
: Class 字段的新标准定义 参考
命令行
preserveWatchOutput
: 发生变化时, 是否保留输出内容
pretty
: 输出内容美化
监听参数 watchOptions
excludeDirectories
: 不跟踪的目录
excludeFiles
: 不跟踪的文件
tsconfig.json 例子
开发环境
{
"extends": "...",
"compilerOptions": {
"outDir": "...",
"rootDir": ".",
"declaration": true,
"declarationMap": true,
"downlevelIteration": true,
"importHelpers": true,
"target": "es2015",
"module": "esnext",
"lib": ["es2017", "dom"],
"strict": true,
"allowSyntheticDefaultImports": true,
"baseUrl": "./",
"esModuleInterop": true,
"moduleResolution": "node",
"inlineSourceMap": true,
"noFallthroughCasesInSwitch": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noPropertyAccessFromIndexSignature": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"disableSizeLimit": true,
"forceConsistentCasingInFileNames": true,
"newLine": "LF",
"noErrorTruncation": true,
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"useDefineForClassFields": true,
"paths": {}
},
"watchOptions": {
"excludeDirectories": ["**/node_modules"]
},
"files": [],
"include": [],
"exclude": [],
}
生产环境
{
"extends": "...",
"compilerOptions": {
"declarationMap": false,
"inlineSourceMap": false,
"noUnusedLocals": true,
"noUnusedParameters": true,
},
"files": [],
"include": [],
"exclude": [],
}