Условные типы с TypeScript - PullRequest
       7

Условные типы с TypeScript

0 голосов
/ 05 сентября 2018

Скажите, у меня есть это:

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>. Если foo равно 'Number', то по умолчанию должно быть number, если foo равно 'Boolean', то по умолчанию должно быть boolean и т. Д. И т. Д.

Ответы [ 2 ]

0 голосов
/ 05 сентября 2018

Вы можете определить ElemType как в ответе Catalyst, а затем использовать сопоставленный тип, чтобы взять объединение 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} | ...
0 голосов
/ 05 сентября 2018

Вы должны сказать машинописи, чтобы как-то проверять фактический объект, и вы не можете по-настоящему убежать без использования обобщений; вот как бы я это сделал:

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
...