基于类型可分配性(兼容性)的自定义 IsAny 和 IsUnknown 泛型 table

Custom IsAny and IsUnknown generic based on type assignability(compatibility) table

我尝试创建基于 thisIsAny 泛型。

我的 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;

TypeScript playground

问题实际上出在 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 的子类型,则结果类型是两个分支的并集。