[英]Typescript: Extend interface dynamically by adding new fields with certain naming
我有一個這樣的界面:
interface ProjectCostData {
purchasePrice: number;
propertyValue: number;
recentlyDamaged: boolean;
}
現在我想根據上面的接口動態創建一個這樣的接口:
interface ProjectCostDataWithSetters {
purchasePrice: number;
setPurchasePrice: Dispatch<SetStateAction<number>>;
propertyValue: number;
setPropertyValue: Dispatch<SetStateAction<number>>;
recentlyDamaged: boolean;
setRecentlyDamage: Dispatch<SetStateAction<boolean>>;
}
--> 映射第一個接口,並為每個條目 A 添加一個新條目 B,其鍵為 `set${entryKey}` 和可以從條目 A 派生的類型。
這在 TS 中可能嗎?
背景:我有一個基於 OpenAPI 的后端,它為我提供 API 結構作為.yaml
文件。 我通過生成器傳遞該文件並接收接口和函數以與 API 對話。 在前端,我使用 react 上下文來構建全局狀態。 我想根據生成器的輸出構建我的全局反應上下文。
在打字稿 4.0 或更早版本中,這是不可能的。 字符串,包括屬性名稱,要么完全稱為常量(即"foo"
)、一組有限可能性的常量之一(即"foo" | "bar"
),或者只是具有任何內容的任何字符串( string
)。 因此,您不能根據其他屬性名稱構造新的屬性名稱。
然而,Typescript 4.1(目前是測試版)有一些特性可能對模板文字類型有幫助
interface ProjectCostData {
purchasePrice: number;
propertyValue: number;
recentlyDamaged: boolean;
}
// Create a new setter property for each key of an interface
type WithSetters<T extends { [k: string]: any }> = T & {
[K in keyof T & string as `set_${K}`]: (newValue: T[K]) => void
}
// Testing
declare const obj: WithSetters<ProjectCostData>
obj.purchasePrice // number
obj.set_purchasePrice(123) // (newValue: number) => void
那:
[K in keyof T & string as `set_${K}`]
有點時髦。 這個 PR 比我能更好地解釋這一點。
您甚至可以處理大小寫變化:
interface Capitals { a: 'A', b: 'B', c: 'C' /* ... */, p: 'P' }
type Capitalize<T extends string> =
T extends `${infer First}${infer Rest}`
? First extends keyof Capitals
? `${Capitals[First]}${Rest}`
: T
: T
type SetterName<T extends string> = `set${Capitalize<T>}`
type SetPropName = SetterName<'propName'> // type: "setPropName"
將所有這些放在一起有點棘手,尤其是在測試版中。 但我認為,從理論上講,實現這種類型轉換的所有部分都存在。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.