基于TypeScript泛型实现工厂函数,根据输入返回对应扩展类
实现类型安全的Base泛型类工厂函数
嘿,你这个需求其实已经有了很好的基础,只需要补全工厂函数的重载定义和实现就能完美实现类型安全啦!我帮你把代码完善好,再给你拆解下关键细节:
class Base<S> { prop: S; constructor(prop: S) { this.prop = prop; } base() { } } class A<S> extends Base<S> { a() { } } class B<S> extends Base<S> { b() { } } interface TypeA { propA: any; } interface TypeB {} function isTypeA(params: TypeA | TypeB): params is TypeA { return (params as TypeA).propA !== undefined; } // 补全工厂函数的重载类型定义,明确不同输入对应的返回类型 function factory(params: TypeA): typeof A; function factory(params: TypeB): typeof B; // 工厂函数实现,用联合类型接收参数,借助类型守卫做分支判断 function factory(params: TypeA | TypeB): typeof A | typeof B { if (isTypeA(params)) { return A; } else { return B; } } // 测试类型安全效果 const aConstructor = factory({ propA: 'test' }); // TypeScript会自动推断aConstructor是typeof A,可以直接创建实例 const instanceA = new aConstructor('hello'); instanceA.a(); // ✅ 类型检查通过,能正常调用A的方法 instanceA.base(); // ✅ 也能调用父类Base的方法 const bConstructor = factory({}); // 自动推断为typeof B const instanceB = new bConstructor(123); instanceB.b(); // ✅ 类型检查通过 instanceB.base(); // ✅ 正常调用父类方法
关键细节说明
- 重载签名的作用:给工厂函数定义两个重载签名后,TypeScript在调用时会根据传入的
params类型,精准推断出返回的构造函数类型(是A还是B),这是实现类型安全的核心。 - 类型守卫的运用:你已经写好的
isTypeA是一个类型谓词函数,它能在运行时判断参数类型,同时告诉TypeScript编译器这个分支里的参数确切类型,让编译器能正确推断返回值类型。 - 泛型的保留:因为A和B都是Base的泛型子类,返回的构造函数会完整保留泛型特性,所以创建实例时传入的
prop类型会被正确绑定到实例的prop属性上。
如果你的需求是让工厂函数直接返回实例而非构造函数,也可以调整成下面这样:
// 直接返回实例的版本 function createInstance<S>(params: TypeA, prop: S): A<S>; function createInstance<S>(params: TypeB, prop: S): B<S>; function createInstance<S>(params: TypeA | TypeB, prop: S): A<S> | B<S> { if (isTypeA(params)) { return new A(prop); } else { return new B(prop); } } // 测试 const instanceA = createInstance({ propA: 'x' }, 'stringProp'); instanceA.a(); // ✅ 类型正确 const instanceB = createInstance({}, 456); instanceB.b(); // ✅ 类型正确
这样不管是返回构造函数还是直接返回实例,都能保证完全的类型安全,TypeScript会在编译阶段就帮你拦截类型错误~
内容的提问来源于stack exchange,提问作者undefined
相关产品推荐
相关产品推荐

