TypeScript 基于差异标记的关系不考虑用作关键字类型的参数,

busg9geu  于 2022-10-29  发布在  TypeScript
关注(0)|答案(4)|浏览(127)

**类型脚本版本:**3.3
代码

type Record2<K extends keyof any, T> = {
    [P in K]: T;
};

function defaultRecord(x: Record<'a', string>, y: Record<string, string>) {
    x = y; // no error, but error expected.
}

function customRecord(x: Record2<'a', string>, y: Record2<string, string>) {
    x = y; // no error, but error expected.
}

function mixed1(x: Record2<'a', string>, y: Record<string, string>) {
    x = y; // error
}

function mixed2(x: Record<'a', string>, y: Record2<string, string>) {
    x = y; // error
}

**Playground链接:**link
相关问题:#28798

kt06eoxx

kt06eoxx1#

这是因为#27804。使用该PR,我们开始测量对象类型和条件类型的类型别名的方差。方差测量逻辑确定K是逆变的,而TRecord<K, T>中是协变的。这 * 几乎 * 是真的:Kstring的示例化与K为文本类型的示例化无关(因为字符串索引签名不满足实际属性)。
@weswigham也许我们应该从方差度量快捷方式中排除Map类型的别名?

mspsb9vt

mspsb9vt2#

感谢您关注这个@ahejlsberg。我想我在使用两个不同别名时看到的差异是因为相同类型的不同别名之间没有共享方差度量?
K是字符串的示例化与K是文本类型的示例化无关(因为字符串索引签名不满足实际属性)。
这似乎是与#28798类似的问题。
我猜想潜在的问题是stringnumber作为值类型的语义与作为键类型的语义不同。通过反转关系,关联键的逻辑可以重用关联值的逻辑,这在大多数情况下有效,但在涉及string时无效。
另一个解决方案(尽管成本更高)是在使用值关系之前使用一个键关系将键类型解释为等价的值类型吗?

x9ybnkn6

x9ybnkn63#

另请参阅#29393,它似乎是别名类型的方差测量的影响。

v8wbuo2f

v8wbuo2f4#

我把标题改成了希望更接近实际问题的东西。如果有误导性,请随意更改。
在您的评论和阅读源代码之后,我现在的理解是,在以下内容之后,可以为参数K推断出一个逆变标记:

isRelatedTo(getConstraintTypeFromMappedType(target), getConstraintTypeFromMappedType(source), reportErrors))

但这没有考虑到K被用作密钥类型的事实,这对吗?
收集uses作为键类型沿着variance,并使用它来正确地确定何时以及 * 如何 * K的两个示例化应该相关,这是完全不合理的吗?我觉得有一些更广泛的问题(#29393)我没有完全理解,所以很可能是完全错误的。
如果#26797着陆,这将是一个问题,我说得对吗?您可以:

interface Record<K extends string,T> {
    [x: K]: T
}

相关问题