簡體   English   中英

推斷 rest 元組類型中的泛型參數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM