推断剩余元组类型中的泛型参数
infer generic parameters in rest tuple type
正在阅读 rest elements in tuple types 并试图找出如何提取类型的通用部分:
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
分支中结束。
最后一步是编写一个使用推断类型作为 return (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);
条件类型没有理由在元组上工作,你的条件类型基本上解决了问题 [typeof Position, typeof Status] extends Attribute<infer T>
,但它显然没有,所以你最终得到了 never。
您可以将联合传递给类型 (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]
正在阅读 rest elements in tuple types 并试图找出如何提取类型的通用部分:
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
分支中结束。
最后一步是编写一个使用推断类型作为 return (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);
条件类型没有理由在元组上工作,你的条件类型基本上解决了问题 [typeof Position, typeof Status] extends Attribute<infer T>
,但它显然没有,所以你最终得到了 never。
您可以将联合传递给类型 (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]