暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

理解并使用 TypeScript 中的 NonNullable 工具类型

背井 2021-05-19
3621

先说说一个常见的问题,你有如下的一个数组:

type NullableNumber = number | null | undefined;const nullableNumbers: ReadonlyArray<NullableNumber> = [123nullundefined];

该数据中既有 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]

参考资料

[1]

官方 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


文章转载自背井,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论