使用 TypeScript 的条件类型

Posted

技术标签:

【中文标题】使用 TypeScript 的条件类型【英文标题】:Conditional types with 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,等等

【问题讨论】:

javascript Conditional Inside TypeScript Interface的可能重复 我更新了 OP,问题似乎有所不同,或者至少该问题的答案不够充分 【参考方案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

【讨论】:

以上是关于使用 TypeScript 的条件类型的主要内容,如果未能解决你的问题,请参考以下文章

mongoose virtuals with typescript error - 包含箭头函数捕获“this”的全局值,该值隐含类型为“any”

TypeScript:条件类型并使用布尔参数来控制返回类型

使用 TypeScript 的条件类型

VS2015 - 更改 TypeScript 版本

TypeScript 中的条件类型

TypeScript 条件类型:从反应组件中提取组件道具类型