首页 > 解决方案 > 推断其余元组类型中的泛型参数

问题描述

阅读元组类型中的剩余元素并尝试找出如何提取类型的通用部分:

type Attribute<Type> = { id: string, type?: Type };

type Position = { x: number, y: number };
let Position: Attribute<Position> = { id: "position" };

type Status = "active" | "inactive";
let Status: Attribute<Status> = { id: "status" };

我确信有一种方法可以编写一个条件类型,它将一个元组映射Attribute<T>到一个元组中T

type AttributeTypes<Attributes extends Attribute<any>[]> =
   Attributes extends Attribute<infer T> ? T[] : never;

type Result = AttributeTypes<[typeof Position, typeof Status]> // should be `[Position, Status]`

但我对推理步骤的理解不够好,它总是在never分支中结束。

最后一步是编写一个使用推断类型作为返回的一部分的函数(Playground):

function getAll<Attributes extends Attribute<any>[]>(
  ...attributes: Attributes
): AttributeTypes<Attributes> {
  return attributes.map(attribute => attribute.type);
}

let [position, status]: [Position, Status] = getAll(Position, Status);

标签: typescriptgenericstuplesinference

解决方案


条件类型没有理由在元组上工作,你的条件类型基本上解决了[typeof Position, typeof Status] extends Attribute<infer T>它显然没有解决的问题,所以你最终得到了永远。

您可以将 union 传递给类型 ( AttributeTypes<typeof Position | typeof Status>),然后您将得到Position[] | Status[]这不是您真正想要的 ( Play )

您也可以在条件类型 ( ) 中使用数组,Attributes extends Array<Attribute<infer T>> ? T[] : never但这不会保留输入 ( Play )中的元组结构

获得所需输出的最佳方法是使用映射类型。映射类型保留元组,同时允许您将元组的每个元素类型映射到结果元组中的新元素类型:

type Attribute<Type> = { id: string, type?: Type };

type Position = { x: number, y: number };
let Position: Attribute<Position> = { id: "position" };

type Status = "active" | "inactive";
let Status: Attribute<Status> = { id: "status" };

type AttributeTypes<Attributes extends Attribute<any>[]> = {
  [P in keyof Attributes]: Attributes[P] extends Attribute<infer T> ? T : never;
}

type Result = AttributeTypes<[typeof Position, typeof Status]> // is [Position, Status]


推荐阅读