TypeScript如何在对象属性赋值后自动推断其具体类型替代预设any
问题原因
你提前给nameToPromise显式指定了带索引签名的NameToPromise类型,该类型的索引签名固定返回Promise<any>,TS会优先使用索引签名的类型定义,不会根据后续赋值窄化单个属性的类型。
解决方案
方案1:不提前指定类型,让TS自动跟踪属性类型
最简便的写法,适合不需要强制限定所有属性必须为Promise类型的场景:
// 不指定类型,直接初始化空对象,TS会自动记录后续添加的所有属性的类型 const nameToPromise = {} // 赋值后TS会自动将someProp的类型标记为Promise<boolean> nameToPromise.someProp = new Promise<boolean>(resolve => setTimeout(() => resolve(true), 100)) // 后续访问时类型推断完全正确 nameToPromise.someProp.then(res => { // res会被自动推断为boolean类型 })
方案2:结合类型断言限定值类型,兼顾校验和类型推断
如果需要保证对象的所有属性值都必须是Promise类型,避免不小心存入非Promise值,可以用这个方案:
// 用类型断言限定所有属性的值必须是Promise类型,同时不固定泛型类型 const nameToPromise = {} as Record<string, Promise<unknown>> // 赋值时会自动校验值是否为Promise类型,同时记录具体的泛型类型 nameToPromise.someProp = new Promise<boolean>(resolve => setTimeout(() => resolve(true), 100)) nameToPromise.anotherProp = new Promise<string>(resolve => setTimeout(() => resolve('test'), 100)) // 类型推断正确:someProp为Promise<boolean>,anotherProp为Promise<string>
方案3:封装工具函数实现更严格的类型安全
如果需要更强的类型约束,避免赋值时写错属性名、类型,可以用断言函数封装实现自动类型扩展:
function createPromiseMap<T extends Record<string, Promise<unknown>> = {}>(initial: T = {} as T) { const map = initial as T & { set<K extends string, V extends Promise<unknown>>(key: K, value: V): asserts map is T & Record<K, V> } map.set = (key, value) => { map[key] = value } return map } // 使用示例 const nameToPromise = createPromiseMap() nameToPromise.set('someProp', new Promise<boolean>(resolve => setTimeout(() => resolve(true), 100))) // 访问时someProp的类型会被正确推断为Promise<boolean>
内容的提问来源于stack exchange,提问作者Sagi Rika
相关产品推荐
相关产品推荐

