【问题标题】:Conditional types with TypeScript使用 TypeScript 的条件类型
【发布时间】:2019-02-10 00:44:59
【问题描述】:

说我有这个:

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&lt;boolean&gt;。如果foo'Number',那么默认应该是number,如果foo 是'Boolean',那么默认应该是boolean,等等

【问题讨论】:

标签: typescript tsc typescript3.0


【解决方案1】:

您可以在 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} | ...

【讨论】:

  • 不完全确定你最后一行在做什么 - 不知道访问器部分是什么 - 你有一个标准接口 {} 但随后访问了 {}[]
  • 这是indexed access type。当[] 中的类型是多个键的并集时,它会生成这些键的值类型的并集。请参阅更新的答案。如果还不清楚,请告诉我。
【解决方案2】:

你必须告诉 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

【讨论】:

    猜你喜欢
    • 2020-03-29
    • 2020-12-14
    • 2018-10-20
    • 1970-01-01
    • 2021-06-29
    • 2019-03-21
    • 1970-01-01
    • 2018-10-31
    • 1970-01-01
    相关资源
    最近更新 更多