Home > Net >  How to fix types mismatch
How to fix types mismatch

Time:09-03

I have constructed quite complicated generic type for function which checks types. The issue has raised with check for Array.

array: <T extends Extract<V, any[]>, V>(val: T | V): val is T

The function is used in many places in the project, but i have problem with the only one usage. As generic expects to get among input types one or more array types, it return val is never if there are not array types.

const func = (notices: Record<any, any>) => {
  if (!is.array(notices)) {
    return
  }

  notices.forEach((notice) => {
    console.log(notice)
  })

And in this place it has become a problem due to notices is typed as never and never has not forEach. I am not sure, but if there is any solution not to break existing logic, but to fix it in this place (preferably without (notices as any[]).forEach, but to fix generic).

Playground link

CodePudding user response:

Updated answer

declare const is: {
  array: (val: unknown): val is unknown[]
}

This is the same thing being done with Array.isArray.

A stricter solution (with better type hinting than Array.isArray) is as follows:

declare const is: {
    // For types which are just array types
    array<T extends Array<unknown>>(val: T | unknown[]): val is T extends Array<infer B> ? B[] : unknown[];
    // For types which contain no array types
    array<T>(val: Exclude<T, Array<unknown>>): val is Exclude<T, Array<unknown>> & unknown[];
    // For types which may contain array types
    array<T>(val: T extends Extract<T, Array<infer B>> ? B[] : Exclude<T, Array<unknown>>): val is T extends Extract<T, Array<infer B>> ? B[] : never;
}

Playground link. Requires typescript>=3.9. For best results, use typescript>=4.3


Previous answer:

Try this:

declare const is: {
    array<T, V>(val: T[] | V): val is T[]
}
  • Related