網站搜尋

javascript - 獲取擴展數組的泛型參數的值


是否有可能檢索一個泛型類型的值,該泛型類型繼承自,例如,string[]?我的使用案例是檢查給定的值是否包含在這個「陣列」中:

function isC<C extends string[]>(attribute: string): attribute is C[number] {
  const valueSet: Set<string> = new Set(C)
  return valueSet.has(attribute)
}

答案#1

TypeScript 的型別系統在 TypeScript 編譯成 JavaScript 時會被刪除,而實際執行的是 JavaScript。因此你的函數編譯後會成為

function isC(attribute) {
    const valueSet = new Set(C); // <-- this C doesn't exist
    return valueSet.has(attribute);
}

這就是編譯器警告你的問題。在你的 JavaScript 代碼中根本不存在 C。C 只是一種 型別,而該型別在運行時並不存在。為了讓這在運行時有任何意義,你需要擁有一個 值,其型別為 C。可能像這樣:

function isC<C extends string[]>(attributes: [...C], attribute: string): attribute is C[number] {
    const valueSet: Set<string> = new Set(attributes)
    return valueSet.has(attribute)
}

那將會有效:

let attr = Math.random() < 0.5 ? "b" : "d";
if (isC(["a", "b", "c"], attr)) {
    console.log({ a: 1, b: 2, c: 3 }[attr]);
} else {
    console.log("nope");
}

不過請注意,特定的實作可能可以進行微調。沒有理由你需要追蹤實際的陣列類型,你只需要元素的字串字面值類型。而且將陣列中的所有元素放入一個Set然後再用has()來檢查是過度的,因為你一旦找到目標元素就可以停止檢查陣列。因此我建議:

function isC<C extends string>(cArray: C[], attribute: string): attribute is C {
    return (cArray as readonly string[]).includes(attribute);
}

那也可以。

程式碼的 Playground 連結