1. unknown
unknown 指的是不可预先定义的类型
,在很多场景下,它可以代替 any 的功能同时保留静态类型检查的能力
,而 any 是放弃了静态检查
1 | const a: unknown = 123; |
unknown 的一个使用场景是,避免使用 any 作为函数的参数类型而导致的静态类型检查 bug:
1 | function test(input: unknown): number { |
2. void
在 TS 中,void 和 undefined 功能高度相似,可以在逻辑上避免不小心使用空指针导致的报错。
1 | function f() {} // 空函数没有任何返回值,返回类型推测为void |
void 和 undefined类型最大的区别是,void并不在意返回值的类型,返不返回 返回什么值都无所谓,undefined则需要返回undefined类型,可以理解为undefined是void的一个子集。
1 | type Fn = () => void; // 这里的void表示逻辑上不关注具体的返回值类型,number、string、undefined等都可以 |
3. never
never 是指没法正常结束返回的类型,一个必定会报错或者死循环的函数会返回这样的类型。
1 | function foo(): never { throw new Error('error message') } // throw error 返回值是never |
还有就是永远没有相交的交叉差类型:
1 | type human = 'boy' & 'girl' // 这两个单独的字符串类型并不可能相交,故human为never类型 |
不过任何类型联合上 never 类型,还是原来的类型:
1 | type language = 'ts' | never // language的类型还是'ts'类型 |
never 还有以下两个特性
- 无法把其他类型赋给 never,any也不行
1
2
3let n: never;
let o: any = {};
n = o; // Error: 不能把一个非never类型赋值给never类型,包括any - 在一个函数中调用了返回 never 的函数后,之后的代码都会变成
deadcode
1
2
3
4
5
6
7
8function foo(): never {
while (true) {}
}
function test() {
foo(); // 这里的foo指上面返回never的函数
console.log(111); // Error: 编译器报错,此行代码永远不会执行到
}
4. const断言
1
2
3
4 它的语法是一个类型断言,用 const 代替类型名称(例如 123 as const)断言构造新的文字表达式时,我们可以向语言发出以下信号:
· 该表达式中的字面类型不应被扩展(例如:不能从“hello”转换为字符串)
· 对象文字获取readonly属性
· 数组文字变成readonly元组
1 | // 写法 |
注意事项
const断言只能立即应用于简单的文字表达式。
1
2
3
4
5
6// Error! A 'const' assertion can only be applied to a
// to a string, number, boolean, array, or object literal.
let a = (Math.random() < 0.5 ? 0 : 1) as const;
// Works!
let b = Math.random() < 0.5 ? (0 as const) : (1 as const);要记住的另一件事是const上下文不会立即将表达式转换为完全不可变的
1
2
3
4
5
6
7
8
9
10
11let arr = [1, 2, 3, 4];
let foo = {
name: "foo",
contents: arr
} as const;
foo.name = "bar"; // error!
foo.contents = []; // error!
foo.contents.push(5); // ...works!
5. 可变参数元祖类型
1 | // 函数concat采用两个数组或元组类型并将它们连接在一起以创建一个新数组。 |
该功能本身很棒,但在更复杂的场景中也很有用。例如,例如实现一个函数 partialCall
,接受一个函数 f
、以及f
期望的最初几个参数,调用后,返回一个新的函数,该函数接受f
需要的剩余参数
1 | type Arr = readonly any[]; |
6. infer
infer 一种类型分发, 表示在 extends
条件语句中推断类型的变量;相当于是一个占位符,给一个 未知的类型 进行推断分发。
简单的例子(获取函数参数)
1 | type ParamType<T> = T extends (param: infer P) => any ? P : T; |
一些用例
tuple 转 union ,如:
[string, number]
->string | number
1
2
3
4
5
6
7
8
9type ElementOf<T> = T extends Array<infer E> ? E : never
type TTuple = [string, number];
type ToUnion = ElementOf<TTuple>; // string | number
方法2:
type TTuple = [string, number];
type Res = TTuple[number]; // string | numberunion 转 intersection,如:
string | number
->string & number
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29分布条件类型
例如:T extends U ? X : Y,当 T 是 A|B 时候,会拆分为A extends U ? X : Y | B extends U ? X : Y
type TypeName<T> = T extends string
? "string"
: T extends number
? "number"
: T extends boolean
? "boolean"
: T extends undefined
? "undefined"
: T extends Function
? "function"
: "object";
type T10 = TypeName<string | (() => void)>; // "string" | "function"
type T12 = TypeName<string | string[] | undefined>; // "string" | "object" | "undefined"
type T11 = TypeName<string[] | number[]>; // "object"
同一类型变量的多个候选类型将会被推断为交叉类型
type Bar<T> = T extends { a: (x: infer U) => void, b: (x: infer U) => void } ? U : never;
type T20 = Bar<{ a: (x: string) => void, b: (x: string) => void }>; // string
type T21 = Bar<{ a: (x: string) => void, b: (x: number) => void }>; // string & number
type UnionToIntersection<U> =
(U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
type Result = UnionToIntersection<{a: string} | {b:number}>; // {a: string} & {b: number}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31interface Action<T> {
payload?: T
type: string
}
interface Module {
count: number;
message: string;
asyncMethod<T, U>(input: Promise<T>): Promise<Action<U>>;
syncMethod<T, U>(action: Action<T>): Action<U>;
}
type Result {
asyncMethod<T, U>(input: T): Action<U>;
syncMethod<T, U>(action: T): Action<U>;
}
将Module转换为Result;
type FuncName<T> = {
[K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];
type TransformF<P> = {
[K in keyof P]: P[K] extends <T, U>(arg: Promise<T>) => Promise<Action<U>>
? <T, U>(arg: T) => Action<U>
: P[K] extends <T, U>(arg: Action<T>) => Action<U>
? <T, U>(arg: Action<T>) => Action<U>
: never;
}
type Result = TransformF<Pick<Module, FuncName<Module>>>;
最后更新: 2021年02月09日 14:24