如何定义TypeScript动态键字典 实现访问不存在Store时报错
核心解决方案
你需要给Registry类增加泛型参数,通过泛型自动推导传入的Store集合的精确类型,替代原来的字符串索引签名,即可实现不存在属性的报错提示。
问题原因
你之前的写法用了{ [name: string]: BaseStore }字符串索引签名,TypeScript会默认所有字符串key都符合类型定义,自然不会对不存在的属性做校验。
修改后的完整代码
registry.ts
// 你已有的BaseStore定义,构造函数接收Registry实例作为参数 export class BaseStore { constructor(public registry: Registry<any>) {} } // 泛型T约束为「键为字符串、值为接收Registry实例的Store构造函数」的对象 export default class Registry<T extends Record<string, new (registry: Registry<T>) => BaseStore>> { // stores的类型和传入的stores的key一一对应,值为对应Store的实例类型 public stores: { [K in keyof T]: InstanceType<T[K]> }; constructor(stores: T) { // 类型断言初始化空对象 this.stores = {} as { [K in keyof T]: InstanceType<T[K]> }; Object.keys(stores).forEach((name) => { const key = name as keyof T; const StoreCls = stores[key]; this.stores[key] = new StoreCls(this); }); } }
实例化Registry示例
import * as stores from './stores.ts'; import Registry from './registry.ts'; // 泛型会自动推断传入的stores的类型,不需要手动传入 const registry = new Registry(stores); // 正常访问,类型为UserStore实例,保留所有自定义属性方法提示 console.log(registry.stores.UserStore); // 正常访问,类型为ListStore实例 console.log(registry.stores.ListStore); // 访问不存在的属性,TypeScript会直接抛出错误提示 console.log(registry.stores.OtherStore);
补充说明
- 如果你希望stores的key为小驼峰格式,比如
userStore而非UserStore,只需要修改stores.ts的导出命名即可,泛型会自动同步推导key的变化。 - 每个store的类型会保留其类定义的专属属性、方法,不会被统一降级为BaseStore类型,不影响正常的类型提示。
内容的提问来源于stack exchange,提问作者Thomas
相关产品推荐
相关产品推荐

