首页 文章

TypeScript的条件类型

提问于
浏览
3

说我有这个:

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'
}

所以默认字段的类型取决于类型字段的值/类型 .

Succintly ,如果 foo'ArrayOfBoolean' ,那么 default 应该是: Array<boolean> . 如果 foo'Number' ,则默认值应为 number ,如果foo为 'Boolean' ,则默认值应为 boolean 等 .

2 回答

  • 2

    您可以在Catalyst的答案中定义 ElemType ,然后使用映射类型将 ElemType 的并集用于所有可能的 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} | ...
    
  • 5

    你必须告诉typescript以某种方式验证实际的obj,如果不使用泛型,你就无法逃脱;我就是这样做的:

    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
    

相关问题