考虑以下代码:
type TestTuple = [
{ test: "foo" },
{
test: "bar";
other: 1;
}
];
type Foo<Prop extends string> = TestTuple extends Record<Prop, string>[]
? true
: false;
type X = Foo<"test">;
type Prop = "test";
type Y = TestTuple extends Record<Prop, string>[]
? true
: false;
// X is type false
const x: X = false;
// Y is type true
const y: Y = true;
Playground link .类型
Foo
和 Y
完全相同,除了 Foo
有一个通用参数 Prop
, 而 Y
只使用一个名为 Prop
的类型别名(不需要类型别名,Y
可以只是 TestTuple extends Record<"test", string>[] ? true : false
但我想让它们的声明完全相同)。所以,Foo<"test">
(别名为 X
类型)和 Y
应该有相同的类型吧?显然不是。 X
如类型 false
而Y
是类型 true
.更改 other
房产在TestTuple
到字符串或完全删除该属性会导致 X
和 Y
是真的,这是预期的行为。所以,我的问题是:这是为什么?这是编译器中的错误吗?如果是这样,是否已经提交了我无法找到的问题?或者,这是在 typescript 中处理泛型的某种奇怪方式吗?
最佳答案
更新 :这已为 TypeScript 4.2 修复:Playground link to code
我已提交 microsoft/TypeScript#41613关于这一点,在简化为以下最小示例之后:
type What<K extends string> =
{ x: { y: 0, z: 1 } } extends { x: { [P in K]: 0 } } ? true : false;
type Huh = What<"y">; // expect true but got false!
TypeScript 首席架构师 Anders Hejlsberg有 commented :When determining whether to defer resolution of the conditional type we relate the "most permissive instantiations" of the check and extends types. The constraint of the most permissive instantiation of the extends type ends up being
{ x: { [index: string]: 0 } }
, but really it should be{ x: { } }
. It's a simple fix and I'll include it in this PR.
所以希望它最终会在 a new PR 中得到修复并可能被 TypeScript 4.2 合并到 TypeScript 中。 (更新:它已被合并。)如果是这样,我希望这应该解决您的问题中的问题,而不是用
{x: ...}
包装索引类型。 ,我们用元组类型包装它。在此之前,您应该考虑使用类似 @Temoncher's answer 中的解决方法。 .
Playground link to code
关于typescript - 具有泛型的类型别名表现出与非泛型类型不同的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64922800/