先说说一个常见的问题,你有如下的一个数组:
type NullableNumber = number | null | undefined;
const nullableNumbers: ReadonlyArray<NullableNumber> = [1, 2, 3, null, undefined];
该数据中既有 number
,又有 null
和 undefined
。
现在,你想把该数组中的 number
都过滤出来形成一个新的数组,所以你写下了如下代码:
const numbers: ReadonlyArray<number> = nullableNumbers
.filter(n => n !== null && n !== undefined);
奇怪的是,编辑器报了一条错误,提示类型不匹配:

尽管它在运行时是正确的,但 TypeScript 没能理解你的代码。
这个问题,我们可以用 type guard 来解决,即给 filter
函数声明返回值的类型:
const numbers: ReadonlyArray<number> = nullableNumbers
.filter((n): n is number => n !== null && n !== undefined);
缺点是,这里的 n is number
是写死的。其实,我们也可以写一个更加通用的 nonNullable filter
函数:
// 通用的 nonnullable filter 函数
const isNonNullable = <T,>(t: T): t is NonNullable<T> => t !== null && t !== undefined;
// 这样使用
const nonNullableNumbers: ReadonlyArray<number> = nullableNumbers.filter(isNonNullable);
注意 <T,>
里的逗号,没有它,TypeScript 会误以为这是个 React Tag ,导致解析错误:

写到这里,你可能会好奇 NonNullable
是什么玩意。
理解 NonNullable
查看 TypeScript 文档,NonNullable
是 Utility Types 的一种。官方对它的解释是 NonNullable<Type>
会将 null
和 undefined
从 Type
中排除掉,由剩余类型组成一个新的类型。
所以,如果我们有:
type Foo = number | null | undefined;
那么 NonNullable<Foo>
就会和 number
就是同一类型:

你可能会好奇 NonNullable
是如何定义的。比如,我可能会把它定义为:
type MyNonNullable<T> = Exclude<T, null | undefined>
这样写没问题,但官方给的定义是这样的:
type NonNullable<T> = T extends null | undefined ? never : T
它把我搞蒙了,因为按这个定义,NonNullable<number | null | undefined>
应该返回 never
,因为 number | null | undefined
extends null | undefined
显然是 true
。你说是不是?
但实际上,这个定义不能这么理解:不能把 number | null | undefined
看成一个整体,而是一个由这3种类型构成的一个类型(可以是 number
,也可以是其它2个),而 NonNullable
的作用,就是从这些类型中排除 null
和 undefined
类型,用剩下的类型组成新的类型。
文章参考
-
官方 NonNullable 文档[1] -
Stackoverflow 问答[2] -
Medium 博客:Nullability in TypeScript[3]
参考资料
官方 NonNullable 文档: https://www.typescriptlang.org/docs/handbook/utility-types.html?#nonnullabletype
[2]
Stackoverflow 问答: How to understand NonNullable in typescript?: https://stackoverflow.com/questions/65147309/how-to-understand-nonnullable-in-typescript
[3]
Medium 博客:Nullability in TypeScript: https://gregoryppabian.medium.com/nullability-in-typescript-60be8c5a6d87
原文始发于微信公众号(背井):理解并使用 TypeScript 中的 NonNullable 工具类型
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/246925.html