unional/type-plus

`IsArray<never[]>` returns `false`

Closed this issue · 7 comments

I don't know if it's by design, but both IsTuple and IsArray return false for never[] in the latest version of type-plus.

These are the relevant tests that don't cover the never[] case (or, as a matter of fact, any complex cases)

it('returns T if T is array', () => {
testType.equal<ArrayType<string[]>, string[]>(true)
})

For IsTuple, never[] returning never is correct because it specifically exclude array as tuple is a more specialized form.

For IsArray, that's probably a bug. But do you have a specific use case for that?

Well, the nature of never means it's not commonly used, so it's not critical.

I may be missing something, but why a more naive solution such as

type AnyArray<T = any> = T[] | ReadonlyArray<T>;

type ArrayType<T, Then = T, Else = never> = IsNever<
  T,
  Else,
  IsAny<T, Else, T extends AnyArray ? Then : Else>
>;

isn't sufficient?

The problem is with the distributive nature of TypeScript.

You can try it out with the tests in https://github.com/unional/type-plus/blob/main/type-plus/ts/array/array_type.spec.ts etc.

I gave it a few shots, but I lack the knowledge. I have no idea how the magic trick of [any[]] extends [T] even makes sense or what [T] extends [readonly any[]] even means.

That is a workaround in TypeScript to avoid the union distribution took place.

Just think of it as a technique you can use when doing your type level programming.