Angular中TypeScript mixins工作原理及使用问题咨询
问题1:mixin使用方式及写法正确性
你当前的mixin写法完全符合Angular生态的规范,和Angular Material官方使用的mixin模式一致,运行逻辑没有问题,只存在类型推导层面的隐性缺陷:mixinTest的泛型约束只声明了入参是ComponentBase的构造器,没有额外保留入参类的全部类型特征,当入参是带泛型的ModelComponentBase时,部分类型信息会在嵌套推导中丢失。
问题2:mixin嵌套顺序/数量影响类型校验的原因
该问题是TypeScript静态类型推导的固有局限导致的,和运行逻辑无关:
- 第一种写法
mixinTest(mixinTest2(ModelComponentBase))<Task>属于两层嵌套泛型同时推导,TS处理最外层mixinTest的返回值类型时,会优先匹配它的泛型约束AbstractConstructor<ComponentBase>,内层mixinTest2返回的带ModelComponentBase特征的类型会被外层约束覆盖,因此丢失了model属性的类型定义 - 调整顺序后
mixinTest2处于最外层,它的泛型约束是AbstractConstructor<ModelComponentBase<unknown>>,推导返回值时会保留model相关的属性定义,类型校验就正常 - 单mixin、分步赋值的写法都规避了TS的多层嵌套泛型推导上限:单mixin没有多层嵌套逻辑,分步赋值时TS会单独推导每一步构造器的类型,不会被外层泛型约束吞没类型特征
问题3:model属性类型异常的修复方案
可以通过给mixin函数增加泛型传递、补充返回值类型断言解决该问题:
第一步:改写mixin的返回值类型,保留入参全部类型特征
// 所有mixin通用的返回值断言写法,保证入参的类型特征不会丢失 export function mixinTest<T extends AbstractConstructor<ComponentBase>>(Base: T) { abstract class MixinTest extends Base { // 原有逻辑 }; // 交叉入参类型和mixin类类型,保留入参的所有属性、泛型特征 return MixinTest as T & AbstractConstructor<MixinTest>; }
第二步:改写mixinTest2的泛型约束,避免写死unknown
// 新增泛型参数T传递Model的类型,不再写死unknown export function mixinTest2<T, U extends AbstractConstructor<ModelComponentBase<T>>>(Base: U) { abstract class MixinTest2 extends Base { // 原有逻辑 }; return MixinTest2 as U & AbstractConstructor<MixinTest2>; }
改写后不管嵌套顺序如何,TS都会保留所有类型特征,不会出现model属性丢失、类型变成unknown | T的问题。
内容的提问来源于stack exchange,提问作者tris
相关产品推荐
相关产品推荐

