Bug报告
🔎 搜索词
- Tagged union
- Discriminated union
- 令人困惑/不清楚的错误信息
🕗 版本与回归信息
此问题在Playground中可用的最旧版本(v3.3)和当前版本(v4.9)上发生。
- 在所有我尝试过的版本中,我都检查了关于区分联合和标记联合的FAQ条目。
⏯ Playground链接
包含相关代码(v4.9.4)的Playground链接。
💻 代码
type DiscriminatedUnion =
| { tag: 'a', data: string }
| { tag: 'b', data: boolean }
| { tag: 'c', data: number }
const myUnion: DiscriminatedUnion = {
tag: 'a',
data: true, // <-- wrong, should be string
}
🙁 实际行为
类型检查器的错误:
Type '{ tag: "a"; data: true; }' is not assignable to type 'DiscriminatedUnion'.
Type '{ tag: "a"; data: true; }' is not assignable to type '{ tag: "c"; data: number; }'.
Types of property 'tag' are incompatible.
Type '"a"' is not assignable to type '"c"'.
🙂 预期行为
应该从类型检查器得到错误,但不是 Type '"a"' is not assignable to type '"c"'.
。在这个例子中,“c”与问题无关,问题是 data
应该是一个 string
,但实际上是一个 boolean
。
我不确定这种情况下的确切错误信息应该是什么样的,大致为 Type 'boolean' is not assignable to type 'string'.
7条答案
按热度按时间kuhbmx9i1#
tag
是一个具有三种可能类型的字段,而data
是一个具有三种可能类型的字段。在确定哪一个是“真正的”判别式方面,实际上没有一种有原则的方法来选择其中一个而不是另一个。寻找这个的代码会选择它找到的第一个看起来像真正判别式的字段,我认为将其转换为排名算法与直接过滤相比并不值得。8e2ybdfx2#
在确定哪个是"真正的"判别式方面,没有一个真正有原则的方法来选择其中一个而不是另一个。
在这种情况下,它不应该总是选择
tag
作为判别式,因为data
不是字面类型的吗?而且,如果它选择data
因为boolean
是true | false
,那么它似乎很奇怪地选择了data
是number
的候选项。0yycz8jy3#
然后,似乎奇怪的是它选择了一个数据是数字的候选项。
是的,这部分很奇怪。我错过了这部分。
我想表达的是,这两个消息都有平等的地位来声称自己是正确的:
因此,在这种情况下,提到c/number是不好的做法。
mqxuamgl4#
@fatcerberus,我猜类型检查器正在做的事情是:
所以看起来错误是用"c"显示的,因为这恰好是最后要检查的情况。
如果我理解正确的话,可能无法(或不切实际)找到一种启发式方法来知道哪些字段是判别标准。由于判别标准/标签与F#/OCaml等相比是“隐式的”,因此编译器不清楚哪个字段实际上是标签。如果多个字段可以作为判别标准,可能会出现组合爆炸的可能性(这是可能的吗?)
理想情况下,编译器的工作原理如下:
但这可能不是一个实际可行的工作流程,具体取决于需要检查的内容的可能性。
vx6bjr1n5#
寻找用于错误报告(以及其他)目的的判别属性是有逻辑的,例如这段代码将根据标签给出不同的错误信息
但是(根据用户反馈!),判别属性不仅仅局限于字面类型:
因此,在OP中,
data
和tag
都被视为判别属性。brvekthn6#
以下是发生的情况:检查器类将
tag
和data
都归类为潜在的判别属性。data
被认为是判别属性的原因是因为类型boolean
是两个文字类型的并集(我们只需要一个文字类型或其并集的存在)。在发现多个候选判别属性时,我们决定完全不进行区分,并选择并集中的最后一个类型用于错误详细说明。我们可能应该只选择第一个候选判别属性,因为那样至少会报告一些更有意义的信息。brccelvz7#
这个问题在5.1.6版本中已经修复。现在的错误是: