基于类型可分配性(兼容性)的自定义 IsAny 和 IsUnknown 泛型 table
Custom IsAny and IsUnknown generic based on type assignability(compatibility) table
我尝试创建基于 this 的 IsAny
泛型。
我的 IsAny
泛型似乎工作正常。
但是当我在另一个通用(IsUnknown
)中使用它时,它被破坏了:
const testIsUnknown2: IsUnknown<any> = true; // problem here, must be false
但是当我将 IsAny
generic 更改为已评论的时,- 它再次正常工作。那么为什么会这样呢?因为我看不出这两个 IsAny
泛型有什么区别,但似乎我的泛型在其他泛型中不起作用。
// type IsAny<T> = 0 extends (1 & T) ? true : false;
type IsAny<T> = unknown extends T ? (T extends object ? true : false) : false;
const testIsAny1: IsAny<any> = true;
const testIsAny2: IsAny<unknown> = false;
const testIsAny3: IsAny<string> = false;
const testIsAny4: IsAny<object> = false;
// unknown is only assignable to two types: unknown and any
type IsUnknown<T> = unknown extends T ? (IsAny<T> extends true ? false : true) : false;
const testIsUnknown1: IsUnknown<unknown> = true;
const testIsUnknown2: IsUnknown<any> = true; // problem here, must be false
const testIsUnknown3: IsUnknown<object> = false;
const testIsUnknown4: IsUnknown<number> = false;
问题是您的 isAny<any>
产生了 boolean
,这意味着这两项作业都将通过:
const testIsAny1: IsAny<any> = true;
const testIsAny2: IsAny<any> = false;
对于其他 isAny
定义,testIsAny2
失败。
关于您对 isAny
的定义,它失败了,因为条件类型 T extends object ? true : false
returns 是 any
的两种选择。我找不到关于此的任何文档,但您可以通过用方括号 (docs):
将两边括起来,以防止条件类型分布在联合上的相同方式修复它
type IsAny<T> = unknown extends T ? ([T] extends [object] ? true : false) : false;
问题实际上出在 IsAny
。
您已经注意到 true: IsAny<any>
,但是,false: IsAny<any>
也!
您已经触及了条件类型的一个可能相当违反直觉的方面。
我举个例子:
type Extends<T, U> = T extends U ? true : false;
我们有:
Extends<'a', 'a' | 'b'> =:= true
Extends<'c', 'a' | 'b'> =:= false
到目前为止没有什么令人惊讶的。
可能令人惊讶的是:
Extends<'a' | 'c', 'a' | 'b'> =:= boolean
当我们有T extends U ? …
时,如果T
的子类型是U
的子类型和是[=的子类型17=] 即 不是 U
的子类型,则结果类型是两个分支的并集。
我尝试创建基于 this 的 IsAny
泛型。
我的 IsAny
泛型似乎工作正常。
但是当我在另一个通用(IsUnknown
)中使用它时,它被破坏了:
const testIsUnknown2: IsUnknown<any> = true; // problem here, must be false
但是当我将 IsAny
generic 更改为已评论的时,- 它再次正常工作。那么为什么会这样呢?因为我看不出这两个 IsAny
泛型有什么区别,但似乎我的泛型在其他泛型中不起作用。
// type IsAny<T> = 0 extends (1 & T) ? true : false;
type IsAny<T> = unknown extends T ? (T extends object ? true : false) : false;
const testIsAny1: IsAny<any> = true;
const testIsAny2: IsAny<unknown> = false;
const testIsAny3: IsAny<string> = false;
const testIsAny4: IsAny<object> = false;
// unknown is only assignable to two types: unknown and any
type IsUnknown<T> = unknown extends T ? (IsAny<T> extends true ? false : true) : false;
const testIsUnknown1: IsUnknown<unknown> = true;
const testIsUnknown2: IsUnknown<any> = true; // problem here, must be false
const testIsUnknown3: IsUnknown<object> = false;
const testIsUnknown4: IsUnknown<number> = false;
问题是您的 isAny<any>
产生了 boolean
,这意味着这两项作业都将通过:
const testIsAny1: IsAny<any> = true;
const testIsAny2: IsAny<any> = false;
对于其他 isAny
定义,testIsAny2
失败。
关于您对 isAny
的定义,它失败了,因为条件类型 T extends object ? true : false
returns 是 any
的两种选择。我找不到关于此的任何文档,但您可以通过用方括号 (docs):
type IsAny<T> = unknown extends T ? ([T] extends [object] ? true : false) : false;
问题实际上出在 IsAny
。
您已经注意到 true: IsAny<any>
,但是,false: IsAny<any>
也!
您已经触及了条件类型的一个可能相当违反直觉的方面。
我举个例子:
type Extends<T, U> = T extends U ? true : false;
我们有:
Extends<'a', 'a' | 'b'> =:= true
Extends<'c', 'a' | 'b'> =:= false
到目前为止没有什么令人惊讶的。
可能令人惊讶的是:
Extends<'a' | 'c', 'a' | 'b'> =:= boolean
当我们有T extends U ? …
时,如果T
的子类型是U
的子类型和是[=的子类型17=] 即 不是 U
的子类型,则结果类型是两个分支的并集。