說我有一個界面
interface Person {
id: string;
name: string;
dob: Date;
dod?: Date;
nicknames?: string[];
age: number;
height: number;
weight: number;
}
我想要一個通用函式,它可以采用這樣的型別并將其映射回僅具有隱式型別的新型別。它還必須能夠根據需要重命名欄位。例如
const a = getThing<Person>({
id: "id" as const, // The const lets TS treat it as a literal and not just any `string`
name: "name" as const,
dateOfBirth: "dob" as const,
});
a
會有型別
{
id: string;
name: string;
dateOfBirth: Date;
}
這可能是不可能的,但我知道這里有很多聰明人。Person
在嘗試使用輸入引數的隱式鍵/值對通用引數 () 進行索引時,我的所有嘗試都卡住了。例如
function getThing<
T,
R = { [k: string]: keyof T }
>(
fields: R
): { [k in keyof R]: T[R[k]] } {
... // implementation unimportant?
}
即使您明確指定 R 的值都是 T 的鍵,您也會在回傳值中得到錯誤R[k] cannot be used to index T
。
我知道 TS 有很多強大的方面,但有時簡單的邏輯東西似乎遙不可及。我使用的是稍舊的 TS 版本,4.3.5,如有必要,也許可以升級。
編輯
當前的方法是否易于修改以允許嵌套欄位?例如,如果 Person 也有一個聯系人欄位:
interface ContactInfo {
homePhone: string;
mobilePhone: string;
email: string;
address: string;
}
interface Person {
...
contact: ContactInfo;
...
}
我們還想映射型別并映射那些子欄位(等等,下到許多級別),在那里我可以獲得結果型別:
{
id: string;
name: string;
dateOfBirth: Date;
ice: { // renamed from `contact`
phone: string; // renamed from `homePhone`
}
}
由于您可能想知道這些瘋狂約束的原因,我正在嘗試構建一個自鍵入 GraphQL 查詢工具。我有可用物件及其欄位的 TS 型別,并且希望隱式創建正確的輸出型別,同時還支持 GQL 欄位重命名行為。當然還有很多其他 GQL 功能,但 99% 的時間我只需要基本型別。
uj5u.com熱心網友回復:
由于 TypeScript 中沒有部分型別推斷,因此您需要在此處使用柯里化:
function getThing<T>() {
return function<R extends Record<keyof any, keyof T>>(remapped: R): {
[K in keyof R]: T[R[K]]
} { return null! }
}
在回傳型別中,您將映射R
并將型別更改為T[R[K]]
因為R[K]
是 的鍵T
。然后你就可以像這樣使用它:
// no 'as const' needed!
const result = getThing<Person>()({
id: "id",
name: "name",
dateOfBirth: "dob",
});
操場
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/529944.html
標籤:打字稿