Why does typescript not recognise my variable is an array after checking function?

I have a simple checking function for array length:

export const hasLength = (arr?: unknown[]) => {
  const isArray = Array.isArray(arr);
  return isArray && arr.length !== 0;
};

I’d expect typescript to recognise that the variable is an array with length after checking through the function but it doesn’t. Is this expected behaviour and why if so?

{hasLength(auction.bids) && (
  <div>
    {[...auction.bids].reverse().map((bid) => null);
  </div>
)}

Error is Type 'string[] | undefined' is not an array type or does not have a '[Symbol.iterator]()' method that returns an iterator.ts

TS Array type

>Solution :

You need a type predicate for the narrowing to "carry over" into the scope it was called:

export const hasLength = (arr: unknown[] | undefined): arr is unknown[] => {
  const isArray = Array.isArray(arr);
  return isArray && arr.length !== 0;
};

If you really need it to be an array of at least length 1, then you can use [T, ...T[]] with a generic:

export const hasLength = <T>(arr: T[] | undefined): arr is [T, ...T[]] => {

Playground

Leave a Reply