Javascript 类型脚本标记的union not type签入开关语句
我使用的是Typescript 3.0.1。在下面的代码中,为什么第7行没有编译器错误?我以前有过这种行为;它是从Typescript中删除的还是有一些奇怪的回归Javascript 类型脚本标记的union not type签入开关语句,javascript,typescript,types,switch-statement,discriminated-union,Javascript,Typescript,Types,Switch Statement,Discriminated Union,我使用的是Typescript 3.0.1。在下面的代码中,为什么第7行没有编译器错误?我以前有过这种行为;它是从Typescript中删除的还是有一些奇怪的回归 type A = {type :"a"} type B = {type :"b"} type Any = A | B function get<T extends Any>(x: T["type"]): T|undefined { switch (x) { case "x": return und
type A = {type :"a"}
type B = {type :"b"}
type Any = A | B
function get<T extends Any>(x: T["type"]): T|undefined {
switch (x) {
case "x": return undefined
default: return undefined
}
}
type A={type:“A”}
类型B={type:“B”}
类型Any=A | B
函数get(x:T[“type”]):T |未定义{
开关(x){
案例“x”:返回未定义
默认值:返回未定义
}
}
问题归结为中的checkSwitchStatement
中的该代码,该代码自2016年以来一直存在:
let caseType = checkExpression(clause.expression);
const caseIsLiteral = isLiteralType(caseType);
let comparedExpressionType = expressionType;
if (!caseIsLiteral || !expressionIsLiteral) {
caseType = caseIsLiteral ? getBaseTypeOfLiteralType(caseType) : caseType;
comparedExpressionType = getBaseTypeOfLiteralType(expressionType);
}
if (!isTypeEqualityComparableTo(comparedExpressionType, caseType)) {
// expressionType is not comparable to caseType, try the reversed check and report errors if it fails
checkTypeComparableTo(caseType, comparedExpressionType, clause.expression, /*headMessage*/ undefined);
}
(存在影响直接比较的类似代码x==“x”
)
a===b
和类似switch语句的规则基于双向类型“可比性”的概念,这一概念(省略了许多不相关的细节)表示,一方的联合成分必须可分配给另一方的联合成分。这被认为是一个启发性的方法来判断两边的类型是否重叠。启发式方法适用于对象的典型使用方式,但不适用于原语,例如,如果a
的类型是受string
约束的某个类型参数T
,我们希望能够将其与“x”
进行比较;已知T
和“x”
都不能分配给另一方,但是T
可以包括“x”
。因此,当比较的一端是文字的并集,而另一端不是时,代码将用底层原语类型替换文字的并集。这种情况在您的代码中触发,其中“x”
是一个文本,T[“type”]
本身不是一个文本,尽管它受到文本并集的约束
我认为我们应该提出一个问题,建议您的代码应该给出一个编译错误。在我写下这句话之后,我看到阿尔特姆提出了一个问题,所以我将在这里添加我的分析
如果您认为您以前遇到过错误,可能您正在考虑以下代码。如果可能的话,类型参数上的属性访问类型将根据类型参数的约束急切地解析,因此y.type
被视为具有类型“a”|“b”
,并且比较的两侧都是文字类型的并集,因此特殊情况不适用
type A = {type :"a"}
type B = {type :"b"}
type Any = A | B
function get<T extends Any>(y: T): T | undefined {
switch (y.type) {
case "x": return undefined
default: return undefined
}
}
type A={type:“A”}
类型B={type:“B”}
类型Any=A | B
函数get(y:T):T |未定义{
开关(y型){
案例“x”:返回未定义
默认值:返回未定义
}
}
看起来像一个bug,我创建了感谢@artem提交这期文章,我会关注它是的,@McCutchen,我相信你的例子就是我以前看到的。我经常感到惊讶的是,打字机脚本推理很少会失败。我们来看看这个问题会有什么结果。