TypeScript 条件类型评估的类型别名产生的结果与它们的等效替换不同,

uqcuzwp8  于 4个月前  发布在  TypeScript
关注(0)|答案(9)|浏览(36)

Bug报告

🔎 搜索词

extends

🕗 版本与回归信息

v4.5.4

⏯ Playground链接

带有相关代码的Playground链接

💻 代码

type S<X> = <T>() => T extends X ? 1 : '2'
type Foo = S<'s1'> 
type Foo2 = S<'s2'>
type Result1 = Foo extends Foo2 ? true : false 

type Result2 = S<'s1'> extends S<'s2'> ? true : false

🙁 实际行为

对于result2表达式,与result1唯一不同的是,result1使用了类型而不是特定的S<'s1'>,但它们返回了完全不同的结果。Result1返回true,Result2返回false

🙂 预期行为

type Result1和type Result2应该返回false

ttvkxqim

ttvkxqim1#

@ahejlsberg昨天提到他正在研究方差计算,这似乎相关。

wmvff8tz

wmvff8tz2#

是的,这里有一个问题。当关联两个从相同起源示例化的签名时,我们擦除类型参数,因为它们已知是相同的。由于擦除替换了 any 类型参数,它导致我们在示例中解决条件类型,而实际上它们应该保持延迟。我认为修复方法是统一签名(通过用另一个的类型参数示例化一个),而不是擦除它们的类型参数。

daolsyd0

daolsyd03#

不确定这是否是一个单独的bug(很乐意提交它——也许@ahejlsberg可以评论?)或者只是这个的一个更糟糕的变化。

type IsItNumber<X> = X extends number ? true : false;
type UnsurprisinglyTrue = (string & number) extends number ? true : false;
type SurprisinglyNever = IsItNumber<string & number>;

不仅通过IsItNumber别名会改变输出,它不知怎么地以never作为结果。

aor9mmx1

aor9mmx14#

我认为这是因为当string & number用作泛型类型参数时,它会被急切地简化为never

jdzmm42g

jdzmm42g5#

@ddurschlag I think this is because string & number is eagerly reduced to never when used as a generic type parameter.
This seems right. Avoiding primitive types produces more sensible results:

type A = {a: 'a'};
type B = {b: 'b'};

type IsItA<X> = X extends A ? true : false;
type Direct = (A & B) extends A ? true : false;
type Indirect = IsItA<A&B>;

I find this combination of sometimes-eager/sometimes-lazy type evaluation difficult to work with. Why is string&number not eagerly reduced in general? Why are some conditional types eagerly evaluated, and some lazily so? At this point, I want a VSCode plugin that shows what TS thinks of my code internally (e.g. which type expressions are eager, which are lazy, which prevent tail recursive evaluation of conditional types, which are having their type parameters erased...). Even worse, I might want the ability to turn off certain eager evaluation optimizations per-line :(

brccelvz

brccelvz6#

IsItNumber<X>中,条件类型是分配条件类型,而在UnsurprisinglyTrue中,条件类型不是。当示例化时,分配条件类型分布在联合类型上,由于never是空的联合类型,所以将分配条件类型应用于never总是产生never

izkcnapc

izkcnapc7#

我已经在#57062上打开了一个重复的问题,我将关闭它以支持这个问题。
然而,仅供信息,这是代码示例。它产生了与上述相同的问题,但略有不同。
Playground链接。

type A<T> = {a: T extends true[] ? true : false};

type B = A<true[]>; // {a: true}
type C = A<boolean[]>; // {a: false}
type D = A<true[]> extends C ? true : false; // `false`, which is correct
type E = A<true[]> extends A<boolean[]> ? true : false; // `true`, which is incorrect

在那段代码中,以下内容可以解决这个问题:

type A<in T> = {a: T extends true[] ? true : false};

另一个解决方法:

type A<T> = {a: T extends true[] ? true : false} & {};
zkure5ic

zkure5ic8#

版本/回归信息:行为在4.2.0-dev.20210111和4.2.0-dev.20210112之间发生了变化。

omqzjyyz

omqzjyyz9#

看起来 #42284 可能是原因,因此这可能是 #42421 的重复(以及 #44119#29698 等?),它们被列为“按预期工作”(尽管对我来说更像是“设计限制”,但🤷‍♂️)。
好的,这对我来说是足够的业余侦探活动。希望它能帮助真正的TS小队进行紧急处理。👦‍🕵️‍♂️

相关问题