Bug报告
你好,
🔎 搜索词
类型缩小、泛型类型、控制流分析
🕗 版本与回归信息
(请查看Playground)尝试缩小泛型类型(联合体)时,控制流分析无法识别到缩小。我还发现这个PR:#43183 本应解决这个问题。
请填写最符合的行:
- 我尝试的每个版本都有这种行为,我查阅了关于类型缩小的常见问题解答
⏯ Playground链接
带有相关代码的Playground链接
💻 代码
const INITIAL_STATE = {
1: 'test1',
2: 'test2',
};
type State = typeof INITIAL_STATE;
const stateReducer = <Type extends keyof State>(
state: State,
action: { type: Type; value: string } | { type: 'clear'; value: number },
) => {
if (action.type === 'clear') {
// action.value is "string | number", but should be "number"
return action.value;
}
return {
...state,
[action.type]: action.value,
};
};
stateReducer(INITIAL_STATE, { type: 'clear', value: 0 });
🙁 实际行为
action.value is "string | number"
🙂 预期行为
应该是 "number"
8条答案
按热度按时间deyfvvtc1#
解:$x_{1m0n1} x$ 不是一个联合体,所以不能像你期望的那样缩小。为了让它工作,你需要把它分布在通用类型 $x_{1m1n1} x$ 上。
$x_{1a0b1} x$
gr8qqesn2#
这是一个公平的问题,为什么
type
不是一个判别属性。这并不是说联合中的每个成分都需要一个单元类型,因为这是可区分的:尽管
Type
是一个类型参数,但它被限制在一个字面类型的联合中,这使得我们无法将其识别为判别属性。条件类型确实分配了,但通过填充约束,它也有点取消泛型化,这让我们能够将其识别为判别属性。我暂时没有看到一个很好的理由,为什么我们不能说一个类型参数的约束是字面类型的有效判别...但这些事情总是会产生意想不到的影响。dauxcl2d3#
这并不是说联盟中的每个成分都需要一个单元类型。
你这么说很有趣,因为这也是我长期以来的理解。这只是因为@RyanCavanaugh过去的评论,我才发现规则是判别式可以是一个单元类型或者一个*单元类型的联合体(这就是为什么
keyof State
作为一个判别式起作用的原因)。所以我当然不会责怪那些没有意识到这一点的人。有趣的是,那个条件类型技巧确实有效。我原以为它会推迟,因为它是在一个类型参数上分配的。
kkih6yb84#
这是一个展示我认为是同样问题的另一个玩具示例:
搜索词:类型保护缩小,可分配给类型为2345的参数
uurity8g5#
另一个在使用泛型和联合时的例子。
我希望
rounds: 1
参数被禁止,因为该属性在ArgonConfig
上不存在。guz6ccqo6#
关于这个问题的更新?我发现自己经常遇到这个问题,尤其是在处理像事件这样的东西时,有多种不同类型和不同有效载荷。这里有一个例子:
(ts playground)
我经常这样做,当为处理多种类型的输入/输出创建抽象时,需要进行类型转换返回类型是很痛苦的。
r6l8ljro7#
这看起来和上面一样,只是泛型被约束在除了联合体之外的其他东西上...但它仍然应该可以区分:
Playground链接
6qftjkof8#
我认为这是一个稍微不同的控制流示例,它没有缩小泛型,只是它不是一个属性访问:
Playground