typescript 检查Array类型的更好方法< any>

wr98u20j  于 2023-03-31  发布在  TypeScript
关注(0)|答案(2)|浏览(151)

我的根本问题是,我需要检测一个类型是Array<any>(不是任何其他Array类型)。
我可以通过两种组合条件检测到这一点:T extends Array<any>Array<any> extends
我如何编写一个条件类型,而不必像下面这样求助于双三进制:

type foo<T> = T extends Array<any> ? Array<any> extends T ? T : 'not any array' : 'not any array';
eh57zj3b

eh57zj3b1#

下面是如何做到我 * 假设 * 你想做的事情(如果需要,请在评论中纠正我)

type IfAny<T, Y, N> = 0 extends (1 & T) ? Y : N;
type IfAnyArray<T, Y, N> = T extends ReadonlyArray<infer V> ? IfAny<V, Y, N> : N;
type IsAnyArray<T> = IfAnyArray<T, 'is any[]', 'is not any[]'>

type test_fooz = IsAnyArray<(number | string)[]>
//   ^?
type test_foo0 = IsAnyArray<number[] | string[]>
//   ^?
type test_foo1 = IsAnyArray<string[]>
//   ^?
type test_foo2 = IsAnyArray<any[]>
//   ^?
type test_foo3 = IsAnyArray<readonly string[]>
//   ^?
type test_foo4 = IsAnyArray<readonly any[]>
//   ^?
type test_foo5 = IsAnyArray<MyArray<string>>
//   ^?
type test_foo6 = IsAnyArray<MyArray<any>>
//   ^?
type test_excb = IsAnyArray<(string & {brand: 'myBrand'})[]>
//   ^?
type test_excB = IsAnyArray<(string & {brand?: 'myBrand'})[]>
//   ^?

class MyArray<T> extends Array<T> {
    x!: number;
}

如果你想要Exclude

type ExcludeArrayOf<T, E> = T extends ReadonlyArray<infer V extends E> ? IfAny<V, T, never> : T;
 
type test_excz = ExcludeArrayOf<(number | string)[], string>
//   ^?
type test_exc0 = ExcludeArrayOf<number[] | string[], string>
//   ^?
type test_exc1 = ExcludeArrayOf<string[], string>
//   ^?
type test_exc2 = ExcludeArrayOf<any[], string>
//   ^?
type test_exc3 = ExcludeArrayOf<readonly string[], string>
//   ^?
type test_exc4 = ExcludeArrayOf<readonly any[], string>
//   ^?
type test_exc5 = ExcludeArrayOf<MyArray<string>, string>
//   ^?
type test_exc6 = ExcludeArrayOf<MyArray<any>, string>
//   ^?
type test_excb = ExcludeArrayOf<(string & {brand: 'myBrand'})[], string>
//   ^?
type test_excB = ExcludeArrayOf<(string & {brand?: 'myBrand'})[], string>
//   ^?
xoshrz7s

xoshrz7s2#

下面是一个只使用1个条件类型的方法,借用了this answer的技巧:

type foo<T> = [1[] & T, any[]] extends [0[], T] ? T : "not any array";

这里有两张支票:一个两个检查any[],另外两个禁止never[]。为了检查any[],我们使用与链接答案相同的原则:any允许我们做一些疯狂的事情,比如将1[]分配给0[]。然而,这也允许never[]溜走。
为了处理never[],我们使用了另一种检查。因为never是底部类型,所以没有任何东西可以分配给它。这意味着我们只需要检查any[]是否可以分配给T
示例测试:

type T01 = foo<any[]>
//   ^? any[]
type T02 = foo<never[]>
//   ^? "not any array"
type T03 = foo<number[]>
//   ^? "not any array"
type T04 = foo<{ bar: any }>
//   ^? "not any array"
type T05 = foo<{ 1: any }>;
//   ^? "not any array"

Playground

相关问题