【问题标题】:Convert optional properties of a TypeScript interface to nullable properties将 TypeScript 接口的可选属性转换为可为空的属性
【发布时间】:2020-02-07 14:50:29
【问题描述】:

我有以下类型:

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">;

但它不起作用。有什么想法吗?

【问题讨论】:

    标签: typescript null undefined conditional-types mapped-types


    【解决方案1】:

    这行得通:

    export type OptionalTuNullable<O> = {
      [K in keyof O]-?: undefined extends O[K] ? NonNullable<O[K]> | null : O[K];
    };
    

    例如:

    type R = {
      a: string;
      b?: string;
      c?: string | null;
      d: string | undefined;
    };
    
    type A = OptionalTuNullable<R>;
    // A: {
    //     a: string;
    //     b: string | null;
    //     c: string | null;
    //     d: string | null;
    // }
    

    然后,对于“Pick”部分,您可以使用标准的Pick 类型:

    type B = Pick<A, "a" | "c">;
    // B: {
    //   a: string;
    //   c: string | null;
    // }
    

    总结起来,我认为这适用于您的用例:

    type VuexPick<T, K extends keyof T> = Pick<OptionalTuNullable<T>, K>
    
    type C = VuexPick<R, 'c'>
    // C: {
    //   c: string | null;
    // }
    
    

    【讨论】:

      【解决方案2】:

      您的类型 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 类型,这会导致应用distributive conditional type,因为T 现在是naked type parameter

      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&lt;string | undefined&gt;B4 相同:

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

      Playground

      【讨论】:

        猜你喜欢
        • 2017-02-04
        • 1970-01-01
        • 2023-04-08
        • 1970-01-01
        • 2023-01-08
        • 1970-01-01
        • 2020-09-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多