[英]Template literal containing keyof used as an interface key
給定一個簡單的界面:
interface Schedule {
interval: "month" | "day";
price: number;
}
我可以構造一個模板文字類型(使用ts4.4
):
type PrefixedScheduleKey = `schedule__${keyof Schedule}`; // "schedule__interval" | "schedule__price"
假設有一些這樣的接口,我想合並(基本上展平)它們的前綴、模板文字鍵,最終得到:
interface Metadata {
foo: string;
bar: string;
// computed
schedule__interval: "month" | "day";
schedule__price: number;
...
}
我應該如何聲明這樣的接口鍵?
interface Metadata {
[key: PrefixedScheduleKey]: any
}
// throws
// An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead.(1337)
和
interface Metadata {
[key in `schedule__${keyof Schedule}`]: any
}
// leads to
// A computed property name must be of type 'string', 'number', 'symbol', or 'any'.(2464)
// Member '[key in `schedule__${keyof' implicitly has an 'any' type.(7008)
這里是游樂場。
順便說一句, 在 github 上建議使用type
而不是interface
但這不起作用,因為我的Metadata
接口已經擴展了另一個接口,但我試圖保持示例簡單。
這不可能直接在接口上執行,如此處所述: Typescript: Mapped types with Interface
到目前為止,在 TypeScript 中(從 2.7.2 版開始),接口中的聯合類型簽名是不允許的,而是應該使用映射類型(正如您正確使用的那樣)。
文檔。
但是,您可以使用任意接口和映射類型之間的交集類型來實現這一點, 如您提到的原始 GitHub 問題(“將其他成員移動到與交集類型組合的單獨對象類型”)。 您還可以使用as
關鍵字有效地內聯您的PrefixedScheduleKey
模板文字類型,同時保留您的Key
足夠長的時間以引用Schedule[Key]
。 沒有理由不能對其他帶前綴的類型執行相同的操作,無論是在相同的映射元數據類型中還是在您稍后與之相交的相鄰元數據類型中。
作為參考,當在映射類型中用作類型變量時, key
大寫為Key
,如映射類型手冊頁中所示。
interface BareMetadata /* extends ArbitraryType */ {
foo: string;
bar: string;
}
type ScheduleMetadata = {
[Key in keyof Schedule as `schedule__${Key}`]: Schedule[Key];
}
type MergedMetadata = BareMetadata & ScheduleMetadata;
const example: MergedMetadata = {
foo: "one",
bar: "two",
schedule__interval: "month",
schedule__price: 9.99
};
您甚至可以讓interface
擴展一個類似對象的type
,這可能會幫助您避免顯式交集:
interface MergedMetadata extends BareMetadata, ScheduleMetadata {}
// or
interface Metadata extends ScheduleMetadata {
foo: string;
bar: string;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.