如何有条件地检测 TypeScript 中的“any”类型?

Ped*_*o A 8 typescript conditional-types

我想一个实用程序,我可以直接使用IsStrictlyAny<T>,它会解决的类型true,如果T是完全any和对false否则类型。我怎样才能做到这一点?

我的第一个想法:

type IsStrictlyAny<T> = any extends T ? true : false;
Run Code Online (Sandbox Code Playgroud)

结果:

  • IsStrictlyAny<any>:(true好!)
  • IsStrictlyAny<unknown>:(true不好!-我想要false
  • IsStrictlyAny<string>:(boolean不好!-我想要false

Ale*_*yne 10

这是一个很好的问题,起初我认为这是不可能的,但经过一番调查后,我认为有办法。

首先,检查一下:

type Test = any extends never ? 'A' : 'B' // "A" | "B"
Run Code Online (Sandbox Code Playgroud)

这意味着打字稿知道这any可以是任何东西,因此它无法决定返回条件的哪一侧,因此它将两侧作为联合返回。我有理由确定这any是唯一会表现出这种方式的情况。

那么你只需要尝试检测是否返回了联合或单个值。为此,我们使用了两种工具。

首先,请注意两个不兼容类型的交集是never

type Test = 'A' & 'B' // never
Run Code Online (Sandbox Code Playgroud)

这是有道理的,因为一个值不能同时是两个不同的字符串。

其次,如果我们可以获得类型联合的所有成员的交集,我们就可以测试它是never,还是任何其他有效类型。这个答案有一个帮手将联合转换为交集,所以我不会费心解释它。

所以有些:

  1. 检查 type 是否将条件的两边作为联合返回
  2. 将联合成员合并成一个交集,看看结果是否为never
type Test = any extends never ? 'A' : 'B' // "A" | "B"
Run Code Online (Sandbox Code Playgroud)

操场

  • 诚然,我的这个答案不是最好的答案! (2认同)

jca*_*alz 8

我找到的最简单的答案是在这个重复的问题的答案中,解释在一个相关的答案中

type IfAny<T, Y, N> = 0 extends (1 & T) ? Y : N; 
type IsAny<T> = IfAny<T, true, false>;

type A = IsAny<any>; // true
type B = IsAny<unknown>; // false
type C = IsAny<string>; // false
type D = IsAny<never>; // false
Run Code Online (Sandbox Code Playgroud)

这样做的简短原因是0 extends (1 & T)对于任何T“遵守规则”的类型都应该是错误的。 0不可分配给1所以它真的不应该分配给1 & T无论是什么T。但any不遵守规则:1 & any评估为any,并且0 extends any为真。

希望有所帮助;祝你好运!

Playground 链接到代码


CRi*_*ice 5

表达方式:

type IsStrictlyAny<T> = (T extends never ? true : false) extends false ? false : true;
Run Code Online (Sandbox Code Playgroud)

符合标准:

type IsStrictlyAny<T> = (T extends never ? true : false) extends false ? false : true;

type t1 = IsStrictlyAny<any>;     // true
type t2 = IsStrictlyAny<unknown>; // false
type t3 = IsStrictlyAny<string>;  // false
type t4 = IsStrictlyAny<never>;   // false!
Run Code Online (Sandbox Code Playgroud)

操场。


这是有效的,因为T extends never ? true : false被视为分布式条件类型时,解析为:

  • boolean如果Tany
  • never如果Tnever
  • false如果T还有别的什么。

然后,由于 和never都可false分配给false,因此最终表达式仅当is时(...) extends false ? false : true才是。trueTany