給定這樣的函式:
function makeObjects<T extends string[]>(...values: T);
將回傳值設為:
T.map(v => ({ [v]: any }));
我正在使用陣列映射來顯示它在我腦海中的樣子,是的,我知道這不是 TS 的作業方式。
uj5u.com熱心網友回復:
我會給它以下呼叫簽名:
declare function makeObjects<T extends string[]>(...values: T):
{ [I in keyof T]: { [P in Extract<T[I], string>]: any } };
(請注意,我尚未實施makeObjects(),并認為這超出了所問問題的范圍)。
回傳型別{[I in keyof T]: ...}是泛型輸入型別引數的鍵上的映射型別。當是陣列或元組型別時,輸出型別也將是陣列或元組型別。TT
I對于輸入陣列 type 中的每個類似數字的索引T,我們希望將元素型別T[I]用作鍵型別。為此,您需要使用另一個映射型別,概念上類似于{[P in T[I]]: any},這意味著“一個物件型別,其鍵T[I]和值是any”。您也可以將其表示為使用Record<T[I], any>實用程式型別。Record<K, V>
不幸的是,雖然您只關心類似數字的索引,但編譯器采用的視圖I可能是的任何鍵T,包括陣列方法名稱,例如"push"and "pop",因此屬性型別T[I]可能是您不想用作的各種東西鍵。(有關此問題的討論,請參閱ms/TS#27995)。
處理這個問題的方法是包裝T[I]一些編譯器會同意的東西,這絕對是 key-like。由于您只關心T[I]成為string(since T extends string[]),我們可以使用實用Extract<T, U>程式型別來過濾T[I]類似字串的東西。
所以這給了你{ [I in keyof T]: { [P in Extract<T[I], string>]: any }}。
讓我們測驗一下:
const foo = makeObjects("a", "b", "c");
// const foo: [{ a: any; }, { b: any; }, { c: any; }]
看起來挺好的; 輸出型別是一個物件元組,其鍵來自對應的引數 to makeObjects()。
Playground 代碼鏈接
uj5u.com熱心網友回復:
您可以使用映射型別Record從以下值創建型別T:
function makeObject<T extends string[]>(...values: T): Record<T[number], any>{
return null!
}
let x = makeObject("a", "b", "c")
x.a
x.d // err
游樂場鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/460171.html
