TypeScript:移除components后如何让方法参数c类型为number而非never
TypeScript类型推断问题修复方案
问题描述
- 注释掉
[AAA.a1][BBB.b1]下的components: [1, 2]时,avaible方法的参数c类型变为never,期望为number - 注释该行后,所有条目(即使其他条目有
components)的avaible参数都会变成(c: never) => {} - 未提供
components属性时,方法参数c需回退为number而非never
原代码
enum AAA { a1 = 'a1', a2 = 'a2', a3 = 'a3', } enum BBB { b1 = 'b1', b2 = 'b2', b3 = 'b3', } type TestData<T extends number = number> = { components?: T[]; avaible: (c: T) => void; } type RR = Partial<Record<AAA, Partial<Record<BBB, number>>>>; type Param<T extends RR> = { [KA in keyof T & AAA]?: { [KB in keyof T[KA] & BBB]?: TestData<Extract<T[KA][KB], number>> } } class Test<T extends RR> { constructor( public readonly data: Param<T> ) { } } new Test( { [AAA.a1]: { [BBB.b1]: { components: [1, 2], // 注释后c应变为number而非never avaible: (c) => { // ^? } }, }, [AAA.a2]: { [BBB.b2]: { components: [5], avaible: (c) => { // ^? } }, [BBB.b1]: { components: [8], avaible: (c) => { // ^? } }, }, } );
问题原因
原Param<T>类型中,当传入对象未给某个条目指定components时,对应的T[KA][KB]会被推断为undefined,Extract<T[KA][KB], number>结果为never,导致TestData的泛型参数为never,最终avaible的参数类型变成never。
修复方案
调整Param类型的映射逻辑,增加条件判断处理未定义的情况,确保没有指定字面量类型时回退到number:
enum AAA { a1 = 'a1', a2 = 'a2', a3 = 'a3', } enum BBB { b1 = 'b1', b2 = 'b2', b3 = 'b3', } type TestData<T extends number = number> = { components?: T[]; avaible: (c: T) => void; } type RR = Partial<Record<AAA, Partial<Record<BBB, number>>>>; // 调整Param类型,支持未定义条目回退到number type Param<T extends RR> = { [KA in keyof T & AAA]?: { // 处理已在T中定义的BBB键 [KB in keyof T[KA] & BBB]?: T[KA][KB] extends number ? TestData<T[KA][KB]> : TestData<number> } & { // 处理未在T中定义的BBB键,直接使用number类型 [KB in Exclude<BBB, keyof T[KA]>]?: TestData<number> } } class Test<T extends RR> { constructor( public readonly data: Param<T> ) { } } new Test( { [AAA.a1]: { [BBB.b1]: { // components: [1, 2], // 注释后c类型为number avaible: (c) => { // ^? 类型为number } }, }, [AAA.a2]: { [BBB.b2]: { components: [5], avaible: (c) => { // ^? 类型为5 } }, [BBB.b1]: { components: [8], avaible: (c) => { // ^? 类型为8 } }, }, } );
修复说明
- 对
T[KA][KB]增加条件判断:如果是number类型则使用对应的字面量类型,否则回退到TestData<number> - 新增
Exclude<BBB, keyof T[KA]>的映射,确保未在T中定义的BBB枚举键也能默认使用number类型的TestData - 保留了原有
components存在时的字面量类型推断,同时解决了未提供components时类型回退的问题
内容的提问来源于stack exchange,提问作者jon
相关产品推荐
相关产品推荐

