如何在TypeScript中正确将用户提供的泛型类型合并到类本身?
解决TypeScript类合并泛型类型的类型报错问题
你的核心需求是让MyClass的实例自动包含传入的ArgSourceT类型的属性,无需每次实例化都手动添加& ArgSourceT的类型断言。以下是两种可行方案:
方案一:指定构造函数返回交叉类型
直接修改构造函数的返回类型为this & ArgSourceT,让TypeScript明确知道实例同时拥有MyClass自身和传入对象的属性:
class MyClass<ArgSourceT> { /** * 实例化类并加载传入对象的属性 * @param source ArgSourceT */ constructor(source: ArgSourceT): this & ArgSourceT { Object.assign(this, source); return this as this & ArgSourceT; } }
使用方式
此时实例化无需额外断言,直接访问传入对象的属性不会报错:
const person = { name: { first: 'John', last: 'Doe', }, }; const myClass = new MyClass(person); console.log('firstname', myClass.name.first); // 类型检查通过
方案二:使用工厂函数封装实例化
如果不想修改类的构造函数返回类型,可以用工厂函数来创建实例,内部自动处理类型合并:
class MyClass<ArgSourceT> { constructor(source: ArgSourceT) { Object.assign(this, source); } } function createMyClass<ArgSourceT>(source: ArgSourceT): MyClass<ArgSourceT> & ArgSourceT { return new MyClass(source) as MyClass<ArgSourceT> & ArgSourceT; }
使用方式
通过工厂函数创建实例:
const person = { name: { first: 'John', last: 'Doe', }, }; const myClass = createMyClass(person); console.log('firstname', myClass.name.first); // 类型检查通过
原理说明
之前的报错是因为TypeScript默认认为MyClass<ArgSourceT>的实例仅包含类自身定义的属性,即便运行时通过Object.assign添加了传入对象的属性,编译时类型系统无法自动识别。通过指定构造函数返回交叉类型,或者用工厂函数封装断言,就能让类型系统感知到合并后的属性。
内容的提问来源于stack exchange,提问作者Zugor
相关产品推荐
相关产品推荐

