TypeScript Never 与 Unknown
本节介绍 never 和 unknown 类型,其中 unknown 类型作为 any 类型对应的安全类型使用起来更加安全,如果有 any 类型的使用需求,应尽量使用 unknown 类型来替代 any 类型。
1. 解释
never
类型表示那些永不存在的值的类型。
unknown
类型是 any
类型对应的安全类型。
2. never 类型
never 类型是任何类型的子类型,也可以赋值给任何类型;然而,没有类型是 never 的子类型或可以赋值给 never 类型(除了 never 本身之外)。 即使 any 也不可以赋值给 never。
2.1 应用场景
一个抛出异常的函数表达式,其函数返回值类型为 never:
function error(message:string): never { throw new Error(message) }
同样的,不会有返回值的函数表达式,其函数返回值类型也为 never:
// 推断的返回值类型为 never function fail(): never { return error("Something failed") }
不能取得值的地方:
interface Foo { type: 'foo' } interface Bar { type: 'bar' } type All = Foo | Bar function handleValue(val: All) { switch (val.type) { case 'foo': break case 'bar': break default: // 此处不能取值 const exhaustiveCheck: never = val break } }
代码解释: 代码中所用到的接口声明(interface)、类型别名(type)、联合类型(A | B)之后都有专门小节介绍。
3. unknown 类型
我们知道 any 无需事先执行任何类型的检查:
let value: any value = true // OK value = 10 // OK value = "Hello World" // OK value = [] // OK value = {} // OK value = Math.random // OK value = null // OK value = undefined // OK value = new TypeError() // OK value = Symbol('name') // OK value.foo.bar // OK value.trim() // OK value() // OK new value() // OK value[0][1] // OK
在许多情况下,这太宽松了。 unknown
类型呢?
let value: unknown value = true // OK value = 10 // OK value = "Hello World" // OK value = [] // OK value = {} // OK value = Math.random // OK value = null // OK value = undefined // OK value = new TypeError() // OK value = Symbol('name') // OK
所有对该 value
变量的分配都被认为是类型正确的。
但是,如果尝试:
let value: unknown let value1: unknown = value // OK let value2: any = value // OK let value3: boolean = value // Error let value4: number = value // Error let value5: string = value // Error let value6: object = value // Error let value7: any[] = value // Error
可以看到,该 unknown 类型只能分配给 any 类型和 unknown 类型本身。
现在继续尝试:
let value: unknown value.foo.bar // Error value.trim() // Error value() // Error new value() // Error value[0][1] // Error
unknown
类型在被确定为某个类型之前,不能被进行诸如函数执行、实例化等操作,一定程度上对类型进行了保护。
在那些将取得任意值,但不知道具体类型的地方使用
unknown
,而非any
。
4. 小结
到本节为止我们介绍了 TypeScript 的各种基本类型。
TypeScript 的类型系统会对数据进行类型检查,它可以在编译阶段规避不必要的错误,并且语义化清晰,有助于代码的阅读。