首页 > 解决方案 > 将 TypeScript 接口的可选属性转换为可为空的属性

问题描述

我有以下类型:

interface A {
  p1: string
  p2?: string
}

我想生成一个子类型B,其中可选属性转换为可为空的属性。相当于:

interface B {
  p1: string
  p2: string | null
}

我试过这样的事情:

type VuexPick<T, K extends keyof T> = {
  [P in K]-?: T[P] extends undefined ? null : T[P];
};

type B = VuexPick<A, "p1" | "p2">;

但它不起作用。任何想法?

标签: typescriptnullundefinedconditional-typesmapped-types

解决方案


您的类型B得到解决:

type B = {
  p1: string extends undefined ? null : string
  p2: string | undefined extends undefined ? null : string | undefined
};

string | undefined由于超类型不扩展undefined,因此相反。所以你最终得到了这种类型:

type B = {
    p1: string;
    p2: string;
}

您可以改为创建一个UndefinedToNull类型,这会导致应用分布式条件类型,就像T现在的裸类型参数一样。

type VuexPick2<T, K extends keyof T> = {
  [P in K]-?: UndefinedToNull<T[P]>;
};

type UndefinedToNull<T> = T extends undefined ? null : T

type B2 = VuexPick2<A, "p1" | "p2">; // type B2 = { p1: string; p2: string | null;}

例如类型UndefinedToNull<string | undefined>B4

type B4 = 
| (string extends undefined ? null: string) 
| (undefined extends undefined ? null: undefined) // type B4 = string | null

操场


推荐阅读