TypeScript泛型构造函数字典类型不匹配问题及解决方案咨询
解决类型不匹配与禁用
any的泛型方案 核心问题分析
- 原字典
ObjStorerDictionary强制所有构造函数接受StoredObj类型,但FooMaker/BarMaker实际要求更具体的Foo/Bar类型,导致类型不兼容。 constructObjectStorerFromJson需要通过泛型关联下拉选项名称与对应参数/返回类型,彻底规避any。
具体修复步骤
1. 定义存储对象的类型映射
创建映射类型,将下拉选项名称与对应的具体存储对象类型绑定:
type StoredObjMap = { "Foo": Foo; "Bar": Bar; };
2. 修正字典的类型定义
基于StoredObjMap重构字典类型,确保每个键对应的构造函数类型精准匹配:
const ObjStorerDictionary: { [K in keyof StoredObjMap]: ObjStorerConstructor<StoredObjMap[K]> } = { "Foo": FooMaker, "Bar": BarMaker, };
此时TypeScript会自动校验每个构造函数的参数类型,原类型不匹配错误将消失。
3. 改造构造函数,移除any
用泛型K约束输入名称为StoredObjMap的键,自动推导参数与返回类型:
const constructObjectStorerFromJson = <K extends keyof StoredObjMap>( name: K, args: StoredObjMap[K] ): ObjStorer<StoredObjMap[K]> => { const Constructor = ObjStorerDictionary[name]; return new Constructor(args); };
现在函数会根据传入的name自动校验args合法性,返回对应类型的ObjStorer实例,完全无需any。
完整代码示例
interface StoredObj { name: string; [key: string]: unknown; }; interface ObjStorer<SpecificStoredObj extends StoredObj> { makeStoredObj: () => SpecificStoredObj } export interface ObjStorerConstructor<SpecificStoredObj extends StoredObj> { new(storedObj: SpecificStoredObj): ObjStorer<SpecificStoredObj> } /////////////// FooMaker //////////////// interface Foo extends StoredObj { name: "Foo", fooProperty: string } class FooMaker implements ObjStorer<Foo>{ constructor(storedObj: Foo) { // do stuff } makeStoredObj(): Foo { return { name: "Foo", fooProperty: "fooo" } } } /////////////// BarMaker /////////////// interface Bar extends StoredObj { name: "Bar", barProperty: string } class BarMaker implements ObjStorer<Bar>{ constructor(storedObj: Bar) { // do stuff } makeStoredObj(): Bar { return { name: "Bar", barProperty: "baaar" } } } ////////////// 类型映射与修正字典 /////////////// type StoredObjMap = { "Foo": Foo; "Bar": Bar; }; const ObjStorerDictionary: { [K in keyof StoredObjMap]: ObjStorerConstructor<StoredObjMap[K]> } = { "Foo": FooMaker, "Bar": BarMaker, }; ////////////// 改造后的构造函数 /////////////// const constructObjectStorerFromJson = <K extends keyof StoredObjMap>( name: K, args: StoredObjMap[K] ): ObjStorer<StoredObjMap[K]> => { const Constructor = ObjStorerDictionary[name]; return new Constructor(args); }; // 合法调用示例 const fooStorer = constructObjectStorerFromJson("Foo", { name: "Foo", fooProperty: "test" }); const barStorer = constructObjectStorerFromJson("Bar", { name: "Bar", barProperty: "test" }); // 非法调用会被TypeScript捕获:参数类型不匹配 // const wrongStorer = constructObjectStorerFromJson("Foo", { name: "Foo", barProperty: "test" });
内容的提问来源于stack exchange,提问作者acenturyandabit
相关产品推荐
相关产品推荐

