在 TypeScript & JavaScript 中有众多的有关“空”、“未定义”的类型:
- null
- undefined
- void
- never
- unknown
本篇文章将辨析以上这些类型。
TypeScript 的类型#
需要注意的是 TypeScript 只是将 ts 语句翻译为 js。换言之 ts 并没有运行时的类型强制。
因此在运行时使用 typeof 并不会显示 void, never 等 ts 特有的类型。
Null & Undefined#
Null
和 Undefined
是 JavaScript(ECMAScript) 中就存在的两个类型。
众所周知的是一个变量(or 对象)必然由两个元素
组成:
数据和结构(即类型)。
在 ECMASCript6 标准中 Undefined
和 Null
是两个基本数据类型,而他们分别之对应了一个值,即为 undefined
和 null
.
二者的区别细微:
null
的本质是一个 object,而 undefined
不是
1
2
3
4
5
6
7
| let a; // undefined
let b = null; // undefined
a == b; // true
typeof a; // undefined
typeof b; // object
let c = Number(a); // c == NaN
let d = Number(b); // d == 0
|
Void#
表示空,通常定义到没有返回值的函数上。
也可以定义到变量上,但是没有什么意义。只能被赋值为 undefined
或null
1
2
3
| function foo(): void {
console.log("something");
}
|
Never#
表示不能触及的、没有返回的。通常在一定抛出异常、或死循环的函数上声明 never 作为返回值类型:
1
2
3
4
5
6
7
8
9
| function foo(): never {
throw new Error("Something")
}
function foo2(): never {
while (true) {
console.log("something")
}
}
|
通过 never 可以实现一些 骚操作
1
2
3
4
5
| type MailHostOf<T> = T extends `${string}@${infer H}.com` ? H : never
type Domain = MailHostOf<"contact@lukasbach.com"> // type is "lukasbach"
type InvalidMail = MailHostOf<"this is no valid email"> // type is never
type AlternativeMail = `noreply@${Domain}.com` // type is "noreply@lukasbach.com"
type InvalidAlternative = `noreply@${InvalidMail}.com` // type is never
|
Unknown#
unknown
和 any
很像。而后者是不被推荐在开发环境中使用的一个类型。
unknown
可以被视为一种更为安全的any
unknown 并不能转换到其他类型,而其他类型的数据可以赋值到 unknown 上。
这里写一个安全的 catch 的代码片段一览 unknown 类型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| // unsafe catch
try {
maybeThrows()
} catch (e: any) {
console.log(e.message)
}
// safe catch
try {
maybeThrows()
} catch(e: unknown) {
if (e instanceof Error) {
console.log(e.message)
// valid
}
}
|
参考文档#