我发现一个有趣的现象,Typescript语言采用了哪些实用类型,哪些没有。例如,NonNullable 是一个内置的实用类型,但Nullable 却不是。
在这篇文章中,我们将快速编写我们自己的Nullable 工具类型,它将允许任何对象的属性为nullable。
我们试图做什么
举个例子说明我们要做的事情:假设我们有一个Person 类型。
type Person = {
name: string;
email: string;
age: number;
admin: boolean;
};
但也许我们有一个接口,我们知道它可能会给我们这些对象属性的任何子集作为null,所以我们想快速派生一个这样的类型。
type NullablePerson = {
name: string | null;
email: string | null;
age: number | null;
admin: boolean | null;
};
我们可能希望Typescript有一个内置的Nullable 类型,但令我们失望的是,它并没有!
启动你自己的可置空的实用类型
幸运的是,一个Nullable 实用类型只有一行长。
type Nullable<T> = { [K in keyof T]: T[K] | null };
而我们可能使用它与我们的Person 类型的方式是这样的。
const nullablePerson: Nullable<Person> = {
name: 'Daffodil',
email: null,
age: null,
admin: true,
};
再往前走一步。深度可空
也许我们有一个用例,我们希望我们的可忽略类型是深入的,这意味着任何数量的对象都是可忽略的。
让我们修改我们的Person 类型,使其拥有另一级的属性。
type Person = {
name: string;
email: string;
age: number;
admin: boolean;
dog: {
name: string;
age: number;
};
};
为了使这个类型深度可归零,我们可以简单地递归调用Nullable 类型中它自己的属性。
type DeepNullable<T> = {
[K in keyof T]: DeepNullable<T[K]> | null;
};
而现在,如果我们在新的Person 类型上实现这一点,我们可以看到我们的对象可以一直是可空的。
const nullablePerson: DeepNullable<Person> = {
name: 'Daffodil',
email: null,
age: null,
admin: true,
dog: {
name: 'Fido',
age: null,
},
};
现在我们可以在任何需要的地方使用这个实用的类型,如果运气好的话,Typescript可能会在某一天把它作为一个内置的类型。