[英]infer generic parameters in rest tuple type
閱讀有關元組類型中的 rest 元素並試圖弄清楚如何提取類型的通用部分:
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" };
我敢肯定有一種方法可以編寫一個條件類型,它將 map 各種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
分支結束。
最后一步是編寫一個 function ,它使用推斷的類型作為返回( 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>
它顯然沒有,所以你最終永遠不會。
您可以將聯合傳入類型( AttributeTypes<typeof Position | typeof Status>
),然后您將獲得Position[] | Status[]
Position[] | Status[]
這不是您真正想要的( Play )
您還可以在條件類型中使用數組( Attributes extends Array<Attribute<infer T>>? T[]: never
),但這不會保留輸入中的元組結構( Play )
獲得您想要的 output 的最佳方法是使用映射類型。 映射類型保留元組,同時允許您將元組的每個元素類型 map 轉換為結果元組中的新元素類型:
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]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.