阅读链接: TypeScript 中的 never unknown
【TypeScript】 never unknown
- TypeScript 2.0 引入了 never,TypeScript 3.0 引入了 unknown
- TypeScript 中的 top type、bottom type
Top type 被称为通用父类型,如 any 、unknown;Bottom type 代表没有值的类型,或者空类型
- unknown 和 any
unknown 表示万物
/*
* any 执行代码时很容易出错,unknown 结合类型守卫确保在上游数据结构不确定时,让代码正确执行
*/
function format1(value: any){
value.toFixed(2) // 不会飘红
}
function format2(value: unknown) {
value.toFixed(2) // 代码会飘红,阻止这样做
// 需要收窄类型范围
1. 类型断言
(value as number).toFixed(2) // 代码不飘红,但执行可能错误
2. 类型守卫
if (typeof value === 'number') {
value.toFixed(2) // 代码不飘红,且正确执行
}
3. 类型断言函数,抛出错误
assertIsNumber(value) // 不飘红,正确执行
value.toFixed(2)
}
function assertIsNumber(arg: unknown): asserts arg is Number {
if (!(arg instanceof Number)) {
throw new TypeError('xx' + arg)
}
}
- never 表示空类型,值永远不存在的类型
值不存在的两种情况:
- 函数执行时抛出异常,函数没有返回值
- 函数中执行无限循环代码,函数没有返回值 ```typescript // 异常 function err(msg: string): never { // OK throw new Error(msg); }
// 死循环 function loopForever(): never { // OK while (true) {}; }
never 是 typescript 唯一一个 bottom type,能够表示任何类型的子类型,所以能够赋值给任何类型。never 除了自身外,没有任何值可以赋值给它,但它可以赋值给任何值<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/399967/1653879991421-6bbd8080-5164-4f65-9f32-8f14f5d8363c.png#clientId=ua01e2f01-cdac-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=324&id=ubfe5d457&margin=%5Bobject%20Object%5D&name=image.png&originHeight=648&originWidth=1080&originalType=binary&ratio=1&rotation=0&showTitle=false&size=78571&status=done&style=none&taskId=u71fe01c5-8aa6-4c29-8ffb-f1c6676be64&title=&width=540)
```typescript
declare const n: never;
let a: null = n; ✅
let b: undefined = n; ✅
let nv: never;
nv = a; ❌
nv = b; ❌
由上: bottom type 是独一无二的,它唯一地描述了函数无返回值的情况
never 的使用场景:
- Unreachable code 检查 ```typescript function listen(): never { //… } listen() // 当 listen 函数给出返回值 never 类型时,编译器会给出如下不可达提示 console.log(‘11’) // Unreachable code detected.ts(7027)
// 例子二 帮助收窄类型 function throwError() { throw new Error(); }
function firstChar(msg: string | undefined) { if (msg === undefined) throwError(); // 如果 throwError 没有给出返回类型 never,则编译器认为下边的代码在任意情况可达,编译器误认为 msg 的类型为 string | undefined,加上类型 never 则 msg 认为是 string let chr = msg.charAt(1) // Object is possibly ‘undefined’. }
- 类型运算
```typescript
// 收窄联合类型,从 T 中排除 null undefined
type NullOrUndefined = null | undefined
type NonNullable<T> = T extends NullOrUndefined ? never : T
- Exhaustive Check:为复合类型创造编译提示(穷尽检查) ```typescript interface Foo { type: ‘foo’ }
interface Bar { type: ‘bar’ }
type All = Foo | Bar | Baz;
function handleValue(val: All) { switch (val.type) { case’foo’: // val 此时是 Foo break; case’bar’: // val 此时是 Bar break; default: // val 此时是 Baz // ❌ Type ‘Baz’ is not assignable to type ‘never’.(2322) const exhaustiveCheck: never = val; break; } } ```