如何更新类实例属性的类型?Builder类store类型未同步问题
解决Builder类中store属性类型无法随addEntry调用同步更新的问题
问题核心在于你的BuilderUsingPlugins类仅用泛型跟踪了插件列表,没有跟踪store的动态结构。TypeScript中类实例的类型是静态绑定的,仅通过方法返回交叉类型无法改变原始实例的静态类型定义。
解决方案:用泛型参数跟踪store的结构
调整类的泛型定义,新增参数S表示当前store的类型,每次调用addEntry时返回更新了S泛型的新实例类型:
type plugin = { name: string, createEntry(...params: any[]): any } type PluginMap<T extends ReadonlyArray<plugin>> = { [key in T[number] as key["name"]]: key["createEntry"] extends ((...args: any[]) => any) ? key["createEntry"] : never } type UsingPluginMap<T extends ReadonlyArray<plugin>, Key extends T[number]["name"]> = PluginMap<T>[Key] class BuilderUsingPlugins<T extends ReadonlyArray<plugin>, S extends Record<PropertyKey, any> = {}> { store: S = {} as S; plugins: PluginMap<T>; addEntry<P extends T[number]["name"], K extends PropertyKey>( pluginValueType: P, name: K, ...pluginParams: Parameters<UsingPluginMap<T, P>> ): BuilderUsingPlugins<T, S & Record<K, ReturnType<UsingPluginMap<T, P>>>> { const entryValue = this.plugins[pluginValueType](...pluginParams); this.store = { ...this.store, [name]: entryValue } as S & Record<K, ReturnType<UsingPluginMap<T, P>>>; return this as BuilderUsingPlugins<T, S & Record<K, ReturnType<UsingPluginMap<T, P>>>>; } constructor(params: T) { this.plugins = params.reduce((acc, curr) => { return { ...acc, ...{ [curr.name]: curr.createEntry } as const satisfies PluginMap<[typeof curr]> }; }, {}) as PluginMap<typeof params>; } } // 插件定义保持不变 const fooPlugin={ createEntry(){ return 'I am the "foo" plugin!' }, name:"foo" } as const satisfies plugin const barPlugin = { name:"bar", createEntry(someparam:number):number{ return someparam } } as const satisfies plugin const bazPlugin = { name:"baz", createEntry(enumishArg:["hello","world"][number]):["hello","world"][number]{ return enumishArg } } as const satisfies plugin const bastoPlugin = { name:"basto", createEntry(enump:ReadonlyArray<string>):typeof enump{ return enump as typeof enump } } as const satisfies plugin const MyPluginList = [fooPlugin,barPlugin,bazPlugin,bastoPlugin] as const // 测试 const builder = new BuilderUsingPlugins<typeof MyPluginList>(MyPluginList); // 接收返回值以获取更新后的类型 const updatedBuilder = builder.addEntry("foo", "fooEntry"); updatedBuilder.store.fooEntry; // 类型正确推断为string // 链式调用时类型自动累积 const chainedBuilder = builder.addEntry("foo", "fooEntry") .addEntry("bar", "barEntry", 123) .addEntry("baz", "bazEntry", "hello"); chainedBuilder.store; // 类型为 { fooEntry: string; barEntry: number; bazEntry: "hello" | "world"; }
关键说明
- 泛型跟踪store结构:通过
S泛型参数记录当前store的所有键值类型,每次调用addEntry时将新键值对类型与原S交叉,生成新的泛型类型。 - 突破静态类型限制:原代码中
store的类型始终是初始的{},因为类的静态类型不会随实例方法调用动态改变。返回新的泛型实例类型后,TypeScript能正确跟踪store的结构变化。 - 简化类型断言:直接通过对象扩展更新
store并断言类型,比原assignAndAssert更简洁,同时保证类型准确。
注意:TypeScript不会自动修改已有变量的静态类型,因此需要用新变量接收
addEntry的返回值才能获取更新后的store类型。若必须复用原变量,可使用类型断言,但会降低类型安全性,不推荐。
内容的提问来源于stack exchange,提问作者A Kam
相关产品推荐
相关产品推荐

