如何在 NaN 和 Infinity 上使用条件类型

How to use conditional types on NaN and Infinity

我正在 TypeScript 中创建一个函数,它实质上扩展了 typeof 关键字的功能,包括在类型已知时(通过条件类型)显示适当的 IntelliSense。我让它适用于我所有其他自定义类型,因此它们只显示已知的 1 return 类型的 IntelliSense,但我不确定如何使其专门用于 NaN 和 Infinity 值。我相信这是因为这些被忽略为“数字”文字类型。 (下面的工作示例)

public static async type(value: number): Promise<'number' | 'nan' | 'infinity'> // would rather this only show just 1 type
public static async type(value: []): Promise<'array'>
public static async type(value: Promise<any>): Promise<'promise'>
// and several more...
public static async type(value: any): Promise<T_detectType> {
   // do stuff
}

我的问题: 是否可以创建基于 NaN and/or Infinity 的条件类型? (下面的非工作示例)

public static async type(value: NaN): Promise<'nan'>
public static async type(value: Number.POSITIVE_INFINITY | Number.NEGATIVE_INFINITY): Promise<'infinity'>

我可以根据需要提供更多详细信息,但我不确定您可能需要什么,我尽量让这个问题简洁明了。

无论好坏,TypeScript 都没有 literal types 表示 NaNInfinity-InfinityNaNInfinity-Infinity 可用的最窄类型只是 number。因此,例如,虽然用数字文字初始化的 const 通常具有文字类型:

const x = 1.234;
// const x: 1.234

NaNInfinity 不会发生同样的情况:

const y = NaN;
// const y: number
const z = -Infinity;
// const z: number

我想不出任何比放弃更糟糕的解决方法。你可以想象提供一些 simulated nominal type

type NaN = number & { NaN: true };
type Infinity = number & { Infinity: true };
type NegInfinity = number & { NegInfinity: true };

但是你需要使用 type assertions 才能使用它们:

const w = NaN as NaN;
const v = Infinity as Infinity;
const u = -Infinity as NegInfinity;

如果你的目标是写 Blah.type(NaN) 并让 Promise<'nan'> 出来,你只能通过写 Blah.type(NaN as NaN) 来实现这个目标,这很愚蠢,尤其是因为没有什么能阻止某人写作 Blah.type(123 as NaN).

在 TypeScript 中,NaNInfinity-Infinity 只是类型 number,仅此而已。


至于改变这个:

microsoft/TypeScript#15135 asking for such support. From reading that issue (and the linked design discussion at ms/TS#15356 有一个功能请求被拒绝)看起来没有人能够清楚地表达一个足够重要的用例来支持它。支持 NaN 作为文字可能会很烦人,因为例如 NaN === NaNfalse.

就我个人而言,我倾向于同意我们关心 NaN 类型,因为实现者 falsy, and tracking falsiness is something worthwhile. But in the pull request implementing numeric literal types, a comment 说它们不重要,他想不出任何有意义的“使用 NaNInfinity 作为单例类型、判别值或文字值进行重载的场景。”

microsoft/TypeScript#32277 有一个未解决的问题,要求 Infinity-Infinity 文字类型而不是 NaN;它目前被标记为“等待更多反馈”,这意味着他们希望在考虑实施之前看到描述令人信服的用例的评论。

并且 microsoft/TypeScript#36964 中存在一个问题,表明缺乏对类似 NaN 的类型的考虑如何导致不正确的缩小...假 number 被假定为 0 而实际上应该是 0 | typeof NaN 才是正确的。它也被标记为等待反馈,请求者似乎在说它应该是 number 因为 typeof NaNnumber(而不是说应该有 NaN类型)。但它是相关的。

几乎可以想象,有足够多的人可以对这两个未解决的问题添加评论,说明应如何添加文字 NaNInfinity-Infinity 类型,并详细说明用例有足够的说服力最终导致这种情况发生。但这很可能不会发生。在我看来,typeof 辅助函数的强类型不太可能被视为特别引人注目。因此,虽然去那里给他们一个并描述你想要做什么可能不会有任何伤害,但我不会指望它有任何效果。

现在,我认为您应该放弃尝试区分 NaNInfinity-Infinitynumber,很遗憾。

Playground link to code