ts泛型的一个小知识

介绍

最近在做type-challenges的时候遇到一个问题:泛型中T extends never与我预期的结果不一致,在查找了一些资料后对这个问题有了新的理解,在这里做一些分享。

原问题要求实现一个泛型工具,判断传入的类型是否为 never,我最开始的答案是:

ts 复制代码
type IsNever<T> = T extends never ? true : false;

对于这个答案,当传入参数为 string、number 等类型的时候,返回的结果是 false,完美符合结果,但是当前的泛型参数为 never 时,T extends never 的判断结果是 false,所以返回的结果是 false,而不是我想要的结果 true

在阅读了 其他人给出的答案后,我发现正确的答案应该是

typescript 复制代码
  type IsNever<T> = [T] extends [never]? true : false

[T] extends [never]?,我相信不止我一个人对此感到困惑,随后,我发现#614对这个问题作出了解释。

对于最初的代码:

ts 复制代码
type IsNever<T> = T extends never ? true : false;

当传入的类型为 string 时,也就是IsNever<string>,这样会抛出一个错误,因为 string 不能赋值给 never 类型。 string extends never 也为假,所以我们得到了一个错误,这是我们预期的结果,是符合我们理解的。

当传入的类型为 never 时,也就是IsNever<never>,我们可能认为 never extends never 为真,那么结果应该是 true ,然而此时的结果却是 false ,这是为什么呢?

事实证明,当 T = never 时,T extends never 并不奏效,但这并不是因为条件语句本身的问题。TypeScript 在解包泛型到条件语句时有一个有趣的特性:它会分配它们。 所以让我们回到分配 never 的问题上。TypeScript 在递归地分配类型联合。另外需要注意的是,没有所谓的联合的联合,联合的联合只是一个更大的联合,包含所有联合中的所有元素。

无论如何,关键在于:TypeScript 在分配条件语句时将 never 视为空联合。这意味着 'a' | never 在分配时会被简化为 'a'。这也意味着 'a' | (never | 'b') | (never | never) 在分配时会变成 'a' | 'b',因为 never 部分相当于空联合,我们可以合并所有的联合。 所以总结一下,TypeScript 在分配条件语句时会忽略空联合。这有道理吧?为什么在没有东西可分配的情况下还要分配呢?(用数学上的概念来理解的话never相当于空集,T extends never可以表述为什么集合包含于空集中,我们知道空集当然什么都不会包含,所以这个条件语句永远都不会成立)

那么,我们如何告诉 TypeScript 不要把 never 视为空联合呢?我们可以强制 TypeScript 在尝试分配之前先评估 T。这意味着我们需要在条件语句中改变 T 类型,以便捕获 T 的 never 值而不丢失。我们这样做是因为我们不能分配一个空联合(即 never)类型的 T。其中一种方法是将 T 放入一个元组:T。这可能是最简单的方法。另一种方法是创建一个 T 的数组:T\[\]。这两个例子都会"评估" T,使其在尝试分配条件语句之前变成其他类型。

Reference

相关推荐
GreenTea6 小时前
GrokBot 核心成员 Lauren Tan:每月交付 2000 个 PR 的人,是怎么用 AI 的
前端·后端·架构
mCell7 小时前
用 Knip 清理 AI Coding 留下的冗余代码
前端·ai编程·前端工程化
笃行3508 小时前
使用Rokid AIUI做了一个童年推箱子游戏
前端
excel9 小时前
前端加密的作用与使用场景
前端
计算机魔术师10 小时前
纽约时报版权诉讼披露:微软高管内部称训练 AI 是人类历史上最大规模劳动窃取
前端
去伪存真11 小时前
大模型的参数量为什么那么大?
前端·人工智能
IT_陈寒11 小时前
Java空指针这次真把我坑惨了
前端·人工智能·后端
掰头战士12 小时前
多重影分身!恨不得把一个agent掰成两个? 还真能干!
typescript·llm·agent
八荒启·交互动画12 小时前
# Web特效020—让 Web 特效真正动起来:时间循环应该怎么接
前端·webgl·网页特效·八荒启-交互动画·八荒启
动恰客流统计12 小时前
线下零售数字化浪潮下,客流统计的3个核心发展趋势
大数据·前端·人工智能