TypeScript泛型映射参数p未收窄为1的原因及无类型转换解法
TypeScript泛型函数类型收窄问题解析
问题原因
泛型参数TT是T的子类型,但TypeScript无法在switch判断t为"a"时,将泛型约束TT与具体字面量类型"a"建立关联,进而推导p的类型为M["a"]。因为TT可能是整个联合类型T,TypeScript无法确定此时TT必然等于"a",所以p的类型会被保留为M[TT](即1 | 2),导致类型报错。
无需类型转换的解决办法
方案1:使用函数重载
为每个参数组合定义明确的重载签名,TypeScript会根据传入的参数自动匹配对应类型,实现过程中能正确收窄类型:
type T = 'a' | "b" type M = { a: 1, b: 2 } function a(a: 'a') {} function m1(a: 1) {} // 重载签名 function f(t: 'a', p: M['a']): void; function f(t: 'b', p: M['b']): void; // 实现签名 function f(t: T, p: M[T]) { switch (t) { case "a": { a(t); m1(p); // 类型正确,p被识别为1 break; } case "b": { // 处理b的逻辑 break; } } }
方案2:合并参数为关联型对象
通过映射类型生成联合类型的参数对象,让TypeScript能通过t的类型自动关联p的对应类型:
type T = 'a' | "b" type M = { a: 1, b: 2 } // 生成包含关联类型的参数联合类型 type Args = { [K in T]: { t: K, p: M[K] } }[T] function a(a: 'a') {} function m1(a: 1) {} function f(args: Args) { switch (args.t) { case "a": { a(args.t); m1(args.p); // 类型正确,p自动收窄为1 break; } } }
内容的提问来源于stack exchange,提问作者Edgar Abgaryan
相关产品推荐
相关产品推荐

