首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >typescript:使用infer永远不会得到不同的结果

typescript:使用infer永远不会得到不同的结果
EN

Stack Overflow用户
提问于 2021-03-04 14:45:54
回答 1查看 134关注 0票数 2

我做了几个演示来重现我的问题。他们来了。

Question1:为什么类型g获取2

代码语言:javascript
复制
// 1
type f = [never] extends [infer S1, ...infer S2]
  ? ([S1] extends [never] ? 1 : 2)
  : 3
// why 2
type g = [never] extends [infer S1, ...infer S2]
  ? ([never] extends [S1] ? 1 : 2)
  : 3

从我的角度来看,类型f等于g,因为S1never

Question2:为什么类型h获取2

代码语言:javascript
复制
// 1
type i = [never] extends [infer S1]
  ? ([never] extends [S1] ? 1 : 2)
  : 3
// why 2
type h = [never] extends [infer S1, ...infer S2]
  ? ([never] extends [S1] ? 1 : 2)
  : 3

从我的角度来看,类型i等于h,因为S2未使用。

Question3:为什么类型k获取never

代码语言:javascript
复制
// 1
type j = [never] extends [infer S1, ...infer S2]
  ? (never extends S1 ? 1 : 2)
  : 3
// why never ?
type k = [never] extends [infer S1, ...infer S2]
  ? (S1 extends never ? 1 : 2)
  : 3

我一点也听不懂。我认为k至少应该是1 2 3的一员。

EN

回答 1

Stack Overflow用户

发布于 2021-03-07 11:19:59

您的问题1和2似乎暴露了TypeScript中的一个错误。

我还希望您的FGHI类型(非原语类型通常是用UpperCamelCase编写的,而不是用lowerCamelCase编写的,这使它们看起来像变量名)的计算结果是1GH的评估结果是2,这一事实令人惊讶。我的研究表明,这种行为是新的;您可以验证您的代码是works as expected in TypeScript 4.1.5的,而不是fails in TypeScript 4.2.2。具体地说,这种变化发生在2021年1月12日或13日左右。你的代码是works as expected in TypeScript 4.2.0-dev.20210112,而是fails in TypeScript 4.2.0-dev.20210113

这种行为很可能是在microsoft/TypeScript#42248合并到主代码分支中时引入的。这个拉取请求修复了一个错误(microsoft/TypeScript#39992),但似乎导致了一些新的错误,如microsoft/TypeScript#42331

我已经提交了microsoft/TypeScrpit#43213来跟踪这个问题。现在,我要说的是,如果你有一个实际的用例需要像上面的GH一样构造,如果你不能等待这个问题得到解决,那么你可以通过使用类型别名而不是空的never来解决它,如下所示:

代码语言:javascript
复制
type N = never
type Gfixed = [N] extends [infer S1, ...infer S2] ? ([N] extends [S1] ? 1 : 2) : 3 // 1

您的问题3的表现与预期相符。在类型K中,(S1 extends never ? 1 : 2)是一个distributive conditional type,因为被检查的类型S1是一个类型参数。这样的类型函数分布在联合上;这意味着如果F<T>是分布的,那么F<X | Y>将等价于F<X> | F<Y>

这意味着F<never>应该是never (或者至少它是F<T>的所有可能答案的子类型)。为什么?因为X | never等同于X,所以F<X | never>必须等同于F<X> | F<never>。这意味着对于所有的XF<X> | F<never>等同于F<X>。那么,从概念上讲,F<never>应该是never

事实证明,当在分布式条件类型中使用时,编译器确实将never视为"the empty union"。当我第一次遇到它的时候,这种行为绝对让我感到惊讶,因为需要有一定的心态转变才能将never视为任何一种联盟。

请注意:

代码语言:javascript
复制
type Distributive<T> = T extends string ? { a: T } : { b: T };

type X = Distributive<"a"> // {a: "a"}
type Y = Distributive<0> // {b: 0}
type Z = Distributive<"a" | 0> // {a: "a"} | {b: 0}

type StillX = Distributive<"a" | never> // {a: "a"}
type Never = Distributive<never> // never

Playground link to code

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66469909

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档