TypeScript中extends条件约束泛型函数报错问题排查
TypeScript泛型函数类型不兼容问题解决
问题描述
我定义了一个getRefCollection泛型函数,要求传入的参数必须是继承自AbstractModel的类,代码如下:
function getRefCollection<T>(Collection: new (tenant: string) => T extends AbstractModel<I> ? T : never) { return new Collection(this.tenantId || '').getModel() }
同时定义了继承自AbstractModel<IReport>的ReportTenant类:
class ReportTenant extends AbstractModel<IReport> { constructor(tenant: string) { super({ name: MODEL.reports, tenant }) } }
调用getRefCollection(ReportTenant)时,TypeScript抛出类型不兼容错误:
Argument of type 'typeof ReportTenant' is not assignable to parameter of type 'new (tenant: string) => never'. Types of construct signatures are incompatible. Type 'new (tenant: string) => ReportTenant' is not assignable to type 'new (tenant: string) => never'. Type 'ReportTenant' is not assignable to type 'never'.ts(2345)
解决方法
方案1:直接约束泛型类型
原函数的泛型约束写法逻辑错误,应该直接对泛型T进行继承约束,而非在构造函数的返回类型中使用条件判断。修正后的代码:
function getRefCollection<T extends AbstractModel<unknown>>(Collection: new (tenant: string) => T) { return new Collection(this.tenantId || '').getModel() }
方案2:保留实体类型的精确约束
如果需要明确AbstractModel的泛型参数,可以额外添加一个泛型参数来承载实体类型,让类型推断更精确:
function getRefCollection<I>(Collection: new (tenant: string) => AbstractModel<I>) { return new Collection(this.tenantId || '').getModel() }
方案3:重载函数(可选)
如果需要更严格的类型检查,可以使用函数重载来明确输入输出类型:
function getRefCollection<T extends AbstractModel<I>, I>(Collection: new (tenant: string) => T): ReturnType<T['getModel']>; function getRefCollection<T extends AbstractModel<any>>(Collection: new (tenant: string) => T) { return new Collection(this.tenantId || '').getModel() }
问题原因
原代码中泛型T没有任何约束,TypeScript无法推断T是否满足T extends AbstractModel<I>的条件,导致条件类型返回never,而传入的ReportTenant构造函数返回的是ReportTenant类型,自然无法赋值给never类型,从而触发报错。直接约束T为AbstractModel的子类后,TypeScript可以正确识别传入的构造函数类型,消除类型不兼容问题。
内容的提问来源于stack exchange,提问作者vy.pham
相关产品推荐
相关产品推荐

