我正在創建一個這樣的通用類:
type Config = {
value: string
}
class MyClass<T> {
configs:{[key in keyof T]: Config },
data: {[key in keyof T]?: string}
constructor(configs: { [key in keyof T]: Config }) {
this.configs = configs;
this.data= {};
}
init() {
Object.entries(this.configs).forEach(([configName, config]) => {
if (!(configName in this.data)) {
this.data[configName] = dosomething(config); // dosomething returns string
}
});
}
}
然后使用如下類:
const cls = MyClass({
cfg1: {value: 'value1'},
cfg2: {value: 'value2'},
})
cls.init();
cls.data預計將是:
{
cfg1: 'calculated1',
cfg2: 'calculated2',
}
但在forEach, configNameisstring和configis 中unknown。
我試過([configName, config]: [key in keyof T, Config]) =>了,但這不起作用。
我怎樣才能做到這一點?
uj5u.com熱心網友回復:
那么該函式Object.entries無法正確推斷此處的型別。當我們查看這個函式的型別定義時,它看起來像這樣:
entries<T>(o: { [s: string]: T } | ArrayLike<T>): [string, T][];
但是您將型別的物件傳遞{ [key in keyof T]: Config }給函式。TypeScript 不認為它們具有可比性,因此[string, unknown][]推斷出型別。
那么你怎么能解決這個問題呢?
選項1
最簡單的方法是更改{ [key in keyof T]: Config }??為{ [key : string]: Config }到處。
configs:{[key : string]: Config }
data: {[key : string]: string}
constructor(configs: { [key : string]: Config }) {
this.configs = configs;
this.data= {};
}
這基本上與您之前的代碼相同。您沒有將型別限制T為具有任何特定形狀,因此T無論如何鍵都可以是任何字串值。事實上,由于我們不再使用T該類,因此不必是泛型的。
讓我知道這是否適用于您的特定用例。或者,如果使用key in keyof T對您有所幫助。
選項 2
第二個選項是設定約束T:
class MyClass2<T extends Record<string, any>> { /* ... */ }
現在 TypeScript 知道keyof T生成string值并推斷出正確的型別。
但是現在我們得到另一個錯誤:
this.data[configName] = dosomething(config)
// Type 'string' cannot be used to index type '{ [key in keyof T]?: string | undefined; }'
這是因為Object.entries將始終string作為元組中的第一個型別回傳,因為它在型別定義中是硬編碼的。
為了解決這個問題,我們(遺憾地)向 TypeScript 提供了更多資訊:
this.data[configName as keyof T] = dosomething(config);
操場
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/472036.html
標籤:打字稿
