如何有条件地检测 TypeScript 中的“任何”类型?
How to conditionally detect the `any` type in TypeScript?
我想要一个可以用作 IsStrictlyAny<T>
的实用程序,如果 T
正好是 any
,它将解析为 true
类型,并且解析为 false
否则键入。我该怎么做?
我的第一个想法:
type IsStrictlyAny<T> = any extends T ? true : false;
结果:
IsStrictlyAny<any>
: true
(好!)
IsStrictlyAny<unknown>
:true
(不好!-我想要false
)
IsStrictlyAny<string>
:boolean
(不好!-我想要false
)
这是个好问题,一开始我觉得不可能,但经过一番调查,我认为有办法。
首先,检查一下:
type Test = any extends never ? 'A' : 'B' // "A" | "B"
这意味着打字稿知道 any
可以是任何东西,因此它无法决定条件的哪一边到 return,所以它的两边都是 return一个工会。我相当确定 any
是唯一会以这种方式表现的情况。
那么您只需要尝试检测联合是 returned 还是单个值。为此,我们使用了两个工具。
首先,注意两个不兼容类型的交集是never
。
type Test = 'A' & 'B' // never
这是有道理的,因为一个值不能同时是两个不同的字符串。
其次,如果我们可以获得类型联合的所有成员的交集,我们就可以测试它是否是 never
,或者它是否是任何其他有效类型。 有个帮手把并集转交集,我就不解释了。
所以对一些人来说:
- 检查是否将 return 条件的两边都键入为并集
- 将并集成员合并成一个交集,看结果是不是
never
。
// From:
type UnionToIntersection<U> =
(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
// If T is `any` a union of both side of the condition is returned.
type UnionForAny<T> = T extends never ? 'A' : 'B'
// Returns true if type is any, or false for any other type.
type IsStrictlyAny<T> =
UnionToIntersection<UnionForAny<T>> extends never ? true : false
type A = IsStrictlyAny<any> // true
type B = IsStrictlyAny<string> // false
type C = IsStrictlyAny<unknown> // false
表达式:
type IsStrictlyAny<T> = (T extends never ? true : false) extends false ? false : true;
符合条件:
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!
这是有效的,因为 T extends never ? true : false
当 treated as a distributed conditional type 解析为:
boolean
如果 T
是 any
。
never
如果 T
是 never
.
false
如果 T
是别的。
然后由于 never
和 false
都可以分配给 false
,因此只有当 T
时,最终表达式 (...) extends false ? false : true
才是 true
是 any
.
我找到的最简单的答案是 , and the explanation is in :
的答案
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
这有效的一个简短原因是 0 extends (1 & T)
对于 "plays by the rules" 的任何类型 T
应该为假。 0
不能分配给 1
所以它真的不应该分配给 1 & T
不管 T
是什么。但是 any
不遵守规则:1 & any
的计算结果为 any
,而 0 extends any
为真。
希望对您有所帮助;祝你好运!
我想要一个可以用作 IsStrictlyAny<T>
的实用程序,如果 T
正好是 any
,它将解析为 true
类型,并且解析为 false
否则键入。我该怎么做?
我的第一个想法:
type IsStrictlyAny<T> = any extends T ? true : false;
结果:
IsStrictlyAny<any>
:true
(好!)IsStrictlyAny<unknown>
:true
(不好!-我想要false
)IsStrictlyAny<string>
:boolean
(不好!-我想要false
)
这是个好问题,一开始我觉得不可能,但经过一番调查,我认为有办法。
首先,检查一下:
type Test = any extends never ? 'A' : 'B' // "A" | "B"
这意味着打字稿知道 any
可以是任何东西,因此它无法决定条件的哪一边到 return,所以它的两边都是 return一个工会。我相当确定 any
是唯一会以这种方式表现的情况。
那么您只需要尝试检测联合是 returned 还是单个值。为此,我们使用了两个工具。
首先,注意两个不兼容类型的交集是never
。
type Test = 'A' & 'B' // never
这是有道理的,因为一个值不能同时是两个不同的字符串。
其次,如果我们可以获得类型联合的所有成员的交集,我们就可以测试它是否是 never
,或者它是否是任何其他有效类型。
所以对一些人来说:
- 检查是否将 return 条件的两边都键入为并集
- 将并集成员合并成一个交集,看结果是不是
never
。
// From:
type UnionToIntersection<U> =
(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
// If T is `any` a union of both side of the condition is returned.
type UnionForAny<T> = T extends never ? 'A' : 'B'
// Returns true if type is any, or false for any other type.
type IsStrictlyAny<T> =
UnionToIntersection<UnionForAny<T>> extends never ? true : false
type A = IsStrictlyAny<any> // true
type B = IsStrictlyAny<string> // false
type C = IsStrictlyAny<unknown> // false
表达式:
type IsStrictlyAny<T> = (T extends never ? true : false) extends false ? false : true;
符合条件:
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!
这是有效的,因为 T extends never ? true : false
当 treated as a distributed conditional type 解析为:
boolean
如果T
是any
。never
如果T
是never
.false
如果T
是别的。
然后由于 never
和 false
都可以分配给 false
,因此只有当 T
时,最终表达式 (...) extends false ? false : true
才是 true
是 any
.
我找到的最简单的答案是
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
这有效的一个简短原因是 0 extends (1 & T)
对于 "plays by the rules" 的任何类型 T
应该为假。 0
不能分配给 1
所以它真的不应该分配给 1 & T
不管 T
是什么。但是 any
不遵守规则:1 & any
的计算结果为 any
,而 0 extends any
为真。
希望对您有所帮助;祝你好运!