

























这是一个创建于 1013 天前的主题,其中的信息可能已经有所发展或是发生改变。
我有一个 Map ,一一对应。
TAP_TYPE.LOCAL 对应 TAP_LOCAL,
TAP_TYPE.MAP 对应 TAP_MAP。
我在函数中已经通过 switch 约束 test 的 v, 为什么 ts 还是推导 v 的类型是 TAP_LOCAL | TAP_MAP ?
或者对这样的例子,除了对 v 进行强制断言,有什么更好的写法吗?
enum TAP_TYPE {
'LOCAL',
'MAP',
}
interface TAP_LOCAL {
a: string;
}
interface TAP_MAP {
b: string;
}
type TapTypeMap = {
[TAP_TYPE.LOCAL]: TAP_LOCAL;
[TAP_TYPE.MAP]: TAP_MAP;
};
function test<T extends TAP_TYPE>(t: T, v: TapTypeMap[T]) {
switch (t) {
case TAP_TYPE.LOCAL:
return v.a; // 类型错误 类型“TAP_LOCAL | TAP_MAP”上不存在属性“a”。
case TAP_TYPE.MAP:
return v.b; // 类型错误 类型“TAP_LOCAL | TAP_MAP”上不存在属性“b”。
}
}
1 Opportunity 2023 年 9 月 7 日当 T=TAP_TYPE 有 t: TAP_TYPE, v: TAP_LOCAL | TAP_MAP 。 我觉得断言已经是最好的方案了,接口上你可以选择使用重载代替泛型,避免 T=TAP_TYPE 这种情况,实现没啥好办法。 |
2 lqzhgood 2023 年 9 月 7 日@Opportunity #1 switch 外层的 v 类型是 TAP_LOCAL | TAP_MAP 没错 后来我想通过函数重载的方式去实现也一样报错了~ ```ts 顺着重载的思路搜到这个 2020 年的帖子 https://www.zhihu.com/question/402139008 |
3 Opportunity 2023 年 9 月 8 日我的意思是,调用方这样写: 如果你硬要把接口搞成这样,就要想办法告诉 TS 两个参数的联系,比如这样写: ``` |
5 chnwillliu 2023 年 9 月 11 日1. switch (t) 缩窄的是变量 t 的类型,并不会影响泛型 T 的范围,就算 T 真能跟随 case 缩窄变化,v:TapTypeMap[T] 也不能获得联动缩窄。T 是一个未知类型,extends 只是约束了这个未知的边界。 enum TAP_TYPE { interface TAP_LOCAL { interface TAP_MAP { type TapTypeMap = { function test<T extends TAP_TYPE>(t: T, v: TapTypeMap[T]): string; |
6 chnwillliu 2023 年 9 月 11 日#3 借助元组进行联动缩窄的方法很巧妙。 |
7 lqzhgood 2023 年 9 月 12 日@chnwillliu #5 我不太明白第二点~ |
8 chnwillliu 2023 年 9 月 12 日 via Android这里就要说到 ts 的 nominal type checking. type foo = 0 & {brand: 'foo'} 这里 foo 并不会是 never ,这是 ts 刻意为之的,虽然运行时不可能存在一种值满足这个类型。(但是可以在 ts 层面 as 啊) type bar = (0 & {brand: 'foo'}) extends 0 ? true : false; // true function test<T extends TAP_TYPE>(t: T, v: TapTypeMap[T]) T 实际有可能是 TAP_TYPE.LOCAL & {a:1} 或与任意其他 interface 的交叉类型。 |
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。