在 TypeScript & JavaScript 中有众多的有关“空”、“未定义”的类型:

  • null
  • undefined
  • void
  • never
  • unknown

本篇文章将辨析以上这些类型。

TypeScript 的类型

需要注意的是 TypeScript 只是将 ts 语句翻译为 js。换言之 ts 并没有运行时的类型强制。

因此在运行时使用 typeof 并不会显示 void, never 等 ts 特有的类型。

Null & Undefined

NullUndefined 是 JavaScript(ECMAScript) 中就存在的两个类型。

众所周知的是一个变量(or 对象)必然由两个元素组成:
数据和结构(即类型)。

在 ECMASCript6 标准中 UndefinedNull 是两个基本数据类型,而他们分别之对应了一个值,即为 undefinednull.

二者的区别细微:
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

表示空,通常定义到没有返回值的函数上。
也可以定义到变量上,但是没有什么意义。只能被赋值为 undefinednull

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

unknownany 很像。而后者是不被推荐在开发环境中使用的一个类型。
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  
		}  
}

参考文档