这与object {} === {}无关,
发现了这个问题不知道这是不是一样
类型集- AUnion不是空集。另外两种类型(L和R)正在扩展它。我的理解是,这些L,R至少和AUnion一样宽,因此我期望L和R中的元素没有空的交点,即AUnion。
我丢失了TypeScript类型系统的哪一部分?
给定TypeScript代码
type AUnion = 'a'|'b';
type Proc = <L extends AUnion, R extends AUnion>(l:L, r:R)=>0|1;
declare const proc:Proc;可以用两个相同的参数调用proc。
const arg:'a' = 'a';
proc(arg,arg); // this is fine (type-wise) 'a' does extend AUnion据我所知,'a'等于'a'。它们的类型是a和a扩展联合类型AUnion。
让我们实现类型。
const proc:Proc = (l, r)=>{
if(l===r){
return 0;
}
return 1;
}然而TypeScript抱怨
This condition will always return 'false' since the types 'L' and 'R' have no overlap.我错过了什么?
发布于 2022-01-09 22:49:10
根据各种GitHub问题,错误的存在是有意的,但错误的确切措辞并不总是合适的。见微软/打字稿#25642,微软/打字稿#27910,微软/打字稿#41402。
如果您有一个类型为X的值y和一个类型为Y的值y,那么是否允许x === y的规则是X和Y必须是“可比较的”。粗略地说,这意味着X extends Y或Y extends X都是正确的。如果这两种情况都不是真的,那么x === y将被禁止。
众所周知,X extends Z和Y extends Z对于第三种类型的Z来说都是正确的,这一事实并没有改变这一点。实际上,类型是顶型 In TypeScript,这意味着X extends unknown和Y extends unknown对于每个X和Y都是正确的。因此,X和Y被限制在某种普通的超级类型上,这并不意味着X和Y是否适合相互比较。
在您的例子中,L extends AUnion和R extends AUnion,但是L extends R和R extends L都不知道是真的。因此编译器不允许进行比较。
至于具体的错误信息的措辞,这是不好的。很明显,当x === y和Y没有“可比性”时,X“总是会返回X”,这是不正确的。当编译器说"X和Y没有重叠“时,听起来肯定是在说"X & Y就是never",但这当然不一定是真的。在这种情况下,总是会返回false (例如,如果X是string,而Y是number,或者X是{z: string},Y是{z: number})。
但是,X & Y的空虚并不是问题所在。编译器将阻止{x: string}和{y: number}的比较,即使交集{x: string; y: number}绝对不是空的。因此,这种比较并不是真正阻止的,因为这两个值不可能是相同的;它是被阻止的,因为比较两种不直接相关的类型通常是错误的指示。
如果要比较编译器认为其类型“不可比较”的两个值,则始终可以将其中一个或两个值扩展为可比较类型。在您的例子中,您知道L和R都可与AUnion相媲美,因此您可以执行以下操作
const proc: Proc = (l, r) => {
const _l: AUnion = l;
const _r: AUnion = r;
if (_l === _r) { // okay
return 0;
}
return 1;
}或
const proc: Proc = (l, r) => {
if (l as AUnion === r) { // okay
return 0;
}
return 1;
}https://stackoverflow.com/questions/70641498
复制相似问题