代码之家  ›  专栏  ›  技术社区  ›  Alexander Mills

带TypeScript的条件类型

  •  4
  • Alexander Mills  · 技术社区  · 6 年前

    假设我有这个:

    type TypeMapping = {
      Boolean: boolean,
      String: string,
      Number: number,
      ArrayOfString: Array<string>,
      ArrayOfBoolean: Array<boolean>
    }
    
    export interface ElemType {
      foo: keyof TypeMapping,
      default: valueof TypeMapping
    }
    

    any 对于默认值,我想有条件地定义它,我尝试了以下方法:

    export interface ElemType<T extends TypeMapping> {
      foo: keyof T,
      default: T
    }
    

    但这似乎不太对,有人知道正确的方法吗?

    如果不清楚,对于任何具有ElemType类型的给定对象,foo指向的键必须与foo指向的值匹配。例如,这是有效的:

    {
      foo: 'String',
      default: 'this is a string'
    }
    

    但这不是:

    {
      foo: 'Boolean',
      default: 'this should be a boolean instead'
    }
    

    有条件的 在类型字段的值/类型上。

    简洁地 ,如果 foo 'ArrayOfBoolean' ,那么 default 应该是: Array<boolean> . 如果 'Number' number ,如果foo是 'Boolean' boolean 等等。

    2 回复  |  直到 6 年前
        1
  •  5
  •   Matt McCutchen    6 年前

    你可以定义 ElemType 如Catalyst的回答中所示,然后使用映射类型接受 元素类型 K :

    interface ElemType<K extends keyof TypeMapping> {
      foo: K;
      default: TypeMapping[K];
    }
    type ElemTypeMap = {[K in keyof TypeMapping]: ElemType<K>};
    // type ElemTypeMap = {
    //   Boolean: {foo: "Boolean", default: boolean},
    //   String: {foo: "String", default: string},
    //   ...
    // }
    type SomeElemType = ElemTypeMap[keyof TypeMapping];
    // Look up in ElemTypeMap by all keys and take the union:
    // {foo: "Boolean", default: boolean} | {foo: "String", default: string} | ...
    
        2
  •  2
  •   Alexander Mills    6 年前

    type TypeMapping = {
      Boolean: boolean;
      String: string;
      Number: number;
      ArrayOfString: Array<string>;
    };
    
    export interface ElemType<K extends keyof TypeMapping> {
      foo: K;
      default: TypeMapping[K];
    }
    
    const Elem = <E extends keyof TypeMapping, T extends ElemType<E>>(t: ElemType<E>) => t;
    
    Elem({ foo: "Boolean", default: true }); //yup
    Elem({ foo: "Boolean", default: "" }); //nope
    
    推荐文章