我正在嘗試創建一個物件,其中每個屬性都映射到一個類實體。型別別依賴于兩個泛型。當我訪問物件中的屬性時,TypeScript 將屬性的型別推斷為用于定義物件的聯合型別,而不是屬性本身的型別。
如何讓 TypeScript 正確推斷屬性的型別?
這是一個有助于澄清問題的代碼片段:
export class CacheWithExpiry<T extends CacheTypes, V extends CacheNames> {
constructor() {
}
...
}
export type CacheNames =
'foo_1' |
'foo_2'
type CacheTypes = string | number
type CacheMap<T extends CacheTypes, V extends CacheNames> = { [key: string]: CacheWithExpiry<T, V> }
export const cacheMap: CacheMap<CacheTypes, CacheNames> = {
foo1Cache: new CacheWithExpiry<string, 'foo_1'>(), // Type is inferred as expected 'CacheWithExpiry<string, "foo_1">'
foo2Cache: new CacheWithExpiry<number, 'foo_2'>()
} as const
cacheMap.foo1Cache// Type is inferred as 'CacheWithExpiry<CacheTypes, CacheNames>' instead of 'CacheWithExpiry<string, "foo_1">'
編輯 1:我還需要維護型別安全,cacheMap因此完全洗掉型別cacheMap是行不通的。例子:
export const cacheMap = {
foo1Cache: new CacheWithExpiry<string, 'foo_1'>(),
foo2Cache: new CacheWithExpiry<number, 'foo_2'>(),
foo3: 'I am not a cache class instance', // I still want this to throw an error
} as const
uj5u.com熱心網友回復:
您將型別分配CacheMap<CacheTypes, CacheNames>給變數cacheMap。此型別不包含任何有關鍵foo1Cache或的資訊foo12ache。它所知道的就是任何型別的鍵都可能包含一個型別string的值CacheWithExpiry<CacheTypes, CacheNames>。這就是為什么當你訪問 的屬性時cacheMap,TypeScript 不會知道具體的屬性。
如果你去掉型別,TypeScript 會知道屬性和它們的型別:
export const cacheMap = {
foo1Cache: new CacheWithExpiry<string, 'foo_1'>(),
foo2Cache: new CacheWithExpiry<number, 'foo_2'>()
} as const
cacheMap.foo1Cache // foo1Cache: CacheWithExpiry<string, "foo_1">
現在的型別cacheMap是:
const cacheMap: {
readonly foo1Cache: CacheWithExpiry<string, "foo_1">;
readonly foo2Cache: CacheWithExpiry<number, "foo_2">;
}
操場
如果在創建物件時還需要型別驗證cacheMap,則需要將物件字面量傳遞給泛型函式。
function createCacheMap<T extends CacheMap<CacheTypes, CacheNames>>(cacheMap: T): T {
return cacheMap
}
export const cacheMap = createCacheMap({
foo1Cache: new CacheWithExpiry<string, 'foo_1'>(),
foo2Cache: new CacheWithExpiry<number, 'foo_2'>(),
anything: "string" // Error: Type 'string' is not assignable to type 'CacheWithExpiry<CacheTypes, CacheNames>
})
cacheMap.foo1Cache // foo1Cache: CacheWithExpiry<string, "foo_1">
操場
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/479135.html
下一篇:從iframe中洗掉選單按鈕
