让每一个对象属性都能在Typescript中归零的方法

87 阅读2分钟

我发现一个有趣的现象,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可能会在某一天把它作为一个内置的类型。