类逆变引用this时如何指定协变泛型约束?
解决TypeScript泛型约束问题:子类不满足父类约束
问题核心在于Context类的pipe属性使用了this类型,导致子类DiffContext的pipe类型为Pipe<DiffContext>,而父类Context的pipe类型是Pipe<Context>。由于Filter类型是(context: TContext) => void(逆变特性),Pipe<DiffContext>无法赋值给Pipe<Context>,最终导致DiffContext不满足Context的泛型约束。
方案一:使用F-bounded泛型约束(推荐)
通过让Context类接受自身类型作为泛型参数,实现子类与父类的类型兼容:
class Context<T extends Context<T>> { pipe?: Pipe<T>; } class DiffContext extends Context<DiffContext> { delta: unknown; } type Filter<TContext extends Context<TContext>> = (context: TContext) => void; class Pipe<TContext extends Context<TContext>> { filters: Filter<TContext>[]; constructor(filters: Filter<TContext>[]) { this.filters = filters; } process(context: TContext) { for (const filter of this.filters) { filter(context); } } } // 现在可正常使用 const testFilter: Filter<DiffContext> = (context) => { console.log(context.delta); }; const pipe = new Pipe<DiffContext>([testFilter]); const context = new DiffContext(); pipe.process(context);
这种方式利用F-bounded多态,让泛型参数T约束为Context<T>,确保子类继承时传递自身类型,既保留了pipe与子类的类型关联,又满足泛型约束的兼容性要求。
方案二:固定pipe的父类类型
如果不需要pipe严格对应子类类型,可以将Context的pipe类型改为Pipe<Context>,放弃this类型的动态绑定:
class Context { pipe?: Pipe<Context>; } class DiffContext extends Context { delta: unknown; } type Filter<TContext extends Context> = (context: TContext) => void; class Pipe<TContext extends Context> { filters: Filter<TContext>[]; constructor(filters: Filter<TContext>[]) { this.filters = filters; } process(context: TContext) { for (const filter of this.filters) { filter(context); } } } const testFilter: Filter<DiffContext> = (context) => { console.log(context.delta); }; const pipe = new Pipe<DiffContext>([testFilter]); const context = new DiffContext(); pipe.process(context);
这种方案简单直接,但会丢失pipe与子类的类型关联,适合不需要子类pipe严格类型化的场景。
内容的提问来源于stack exchange,提问作者Nathan Bierema
相关产品推荐
相关产品推荐

