杂记 - TypeScript 4.2

使用规范

  • 尽量不使用断言 ! ?
  • 使用 unknown 而不是 any
  • 泛型在 interfacetype 同样实用
  • 不要在模块中使用 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");
    }
})

模块

顶层有 importexport 被视为模块, 反之为脚本, 脚本具有全局作用域.

export = 导出 CommonJSAMD 模块, import = require() 导入

相对导入( \ , .\ , ..\ )不会被解析为环境模块声明, 非相对导入可以被解析为环境模块声明

import type 导入类型定义

模块解析策略

  • Classic
  • Node

函数

如果函数不声明返回类型, 会根据 return 语句自动推断, 无 returnreturn 后面不带内容, 则为 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();
  1. 初始化基类字段
  2. 运行基类构造函数
  3. 初始化派生类字段
  4. 运行派生类构造函数

内置的类型函数

用法 注释
Partial -
Required -
Readonly -
Record 定义对象的属性类型为 Keys , 值类型为 Type
Pick 从对象类型 Type 中选择一组 Keys 作为新的对象类型
Omit Pick 相反, 排除 Keys
Exclude 联合类型 Type 排除 ExcludedUnion
Extract Exclude 相反, 包含 Union
NonNullable Type 不包含 nullundefined
Parameters Type 的参数类型(元组), 没有为 never
ConstructorParameters Type 的构造函数参数类型(元组), 没有为 never
ReturnType Type 的返回值类型, 没有为 any
InstanceType Type 的实例类型, 没有为 any
ThisParameterType Typethis 类型, 没有为 unknown
OmitThisParameter 去除 Typethis 类型声明
ThisType 非转换, 声明 this 类型, 开启 --noImplicitThis
Uppercase -
Lowercase -
Capitalize -
Uncapitalize -

装饰器

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 , SystemAMD

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 : 开启 sourceMapinlineSourceMap , 与 inlineSourceMap 表现相同

mapRoot : 指定源地图位置

sourceRoot : 指定源位置

Linter检查

noFallthroughCasesInSwitch : switch 语句包含 breakreturn

noImplicitOverride : 子类函数重载, 必须含关键字 override

noImplicitReturns : 确保所有可能的返回值被检查

noPropertyAccessFromIndexSignature : 确保 obj.keyobj["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": [],
}

你可能感兴趣的:(杂记,typescript)