TypeScript约束顺序方法调用:实现同泛型形状组件的类型断言API
问题:创建兼具运行时API与类型断言的接口报错
我想创建一个同时支持运行时API和类型断言的接口,要求传入的两个组件必须基于相同形状的泛型。但代码一直报错,错误信息如下:
Argument of type 'typeof A' is not assignable to parameter of type 'Component<any>'. Property '[S]' is missing in type 'typeof A' but required in type 'Component<any>'.
相关代码示例:
import {expectTypeOf} from 'expect-type'; declare const S: unique symbol; declare class Component<S> { declare private [S]: S; } type InferSignature<T> = T extends Component<infer Signature> ? Signature : never; declare class A extends Component<{ name: string; age: number; }> {}; declare class B extends Component<{ mismatch: true }> {} function fromThis<T extends Component<any>>(ThisComponent: T) { return { toThat<R extends Component<InferSignature<T>>>(ThatComponent: R) { return { withRuntimeTest( testName: string) { if (window.location.search.includes(testName)) { return ThatComponent; } return ThisComponent; } } } } } // 类型推断正常 type ASig = InferSignature<A>; type BSig = InferSignature<B>; // 这是我期望的断言行为 expectTypeOf<ASig>().toEqualTypeOf(BSig) // 但这里的类型检查不符合预期 fromThis(A).toThat(B).withRuntimeTest('my-b-test')
问题分析与修复方案
错误原因
报错的核心是:Component类中定义的私有符号属性[S]不会被子类的构造函数类型继承。我们传入的A和B是类本身(构造函数),而非类的实例,但原代码的类型约束T extends Component<any>是针对实例类型的,导致类型不匹配。
修复后的完整代码
import {expectTypeOf} from 'expect-type'; declare const S: unique symbol; declare class Component<S> { declare private [S]: S; } // 调整工具类型:从组件构造函数中提取泛型签名 type InferSignature<T> = T extends typeof Component<infer Sig> ? Sig : never; declare class A extends Component<{ name: string; age: number; }> {}; declare class B extends Component<{ mismatch: true }> {} // 约束参数为Component的子类构造函数类型 function fromThis<T extends typeof Component<any>>(ThisComponent: T) { return { // 强制目标组件的泛型签名与源组件完全一致 toThat<R extends typeof Component<InferSignature<T>>>(ThatComponent: R) { return { withRuntimeTest(testName: string) { if (window.location.search.includes(testName)) { return ThatComponent; } return ThisComponent; } } } } } // 类型推断正常工作 type ASig = InferSignature<A>; type BSig = InferSignature<B>; // 这里会正确触发类型错误,符合预期的断言行为 expectTypeOf<ASig>().toEqualTypeOf(BSig) // 仅当传入泛型签名匹配的组件时才通过类型检查 // fromThis(A).toThat(A).withRuntimeTest('my-a-test') // 合法 fromThis(A).toThat(B).withRuntimeTest('my-b-test') // 正确报错:类型不匹配
关键修复点
- 调整类型约束对象:将
fromThis的参数约束从实例类型Component<any>改为构造函数类型typeof Component<any>,匹配我们传入的类本身。 - 更新泛型提取逻辑:修改
InferSignature工具类型,从构造函数类型中正确提取泛型参数。 - 强化类型断言:
toThat的约束R extends typeof Component<InferSignature<T>>确保目标组件的泛型签名与源组件完全一致,实现了预期的类型校验,同时保留原有的运行时逻辑。
内容的提问来源于stack exchange,提问作者Chad
相关产品推荐
相关产品推荐

