Check variable is either array of custom type or array of arrays of that type

I am chunking an array into smaller pieces if the original is longer than a specified amount, and I am wanting to perform a different action depending on if it is a 1D or 2D array.

type MyType = {
    id: string;
    name: string;
}

const performChunking = (arr: MyType[], CHUNK_MAX: number): MyType[] | MyType[][] => {
    if (!(arr.length > CHUNK_MAX)) return arr;

    let chunkedArray: MyType[][];
    // Perform chunking
    return chunkedArray;
}

const values: MyType[] | MyType[][] = performChunking(someArr, 5);

/*
    Here I want to perform something like

    if (typeof values === MyType[][]) {
        // return something;
    }

    // return something else
*/

I have looked at instanceOf but that doesn’t accept arrays it seems.

First, TypeScript types do not exist at runtime. They are erased during compilation. Therefore runtime checks like if (typeof values === MyType[][]) are not possible.

One way to ensure that a variable is of some specific type is by using a type predicate. In the example below I checked whether the first item in MyType[] is an array. If so, we know we’re dealing with a nested array of type MyType[][].

There’s just one problem: [] is assignable to MyType[][] as well. So you might want to change the type of the nested array to something like [MyType[], ...MyType[][]]. That ensures an array contains at least one item.

type MyType = {
  id: string;
  name: string;
};

const performChunking = (
  arr: MyType[],
  CHUNK_MAX: number,
): MyType[] | [MyType[], ...MyType[][]] => {
  if (!(arr.length > CHUNK_MAX)) return arr;

  const chunkedArray: [MyType[], ...MyType[][]] = [[{ id: "", name: "" }]];
  // Perform chunking
  return chunkedArray;
};

declare const someArr: MyType[];
const values: MyType[] | [MyType[], ...MyType[][]] = performChunking(
  someArr,
  5,
);

function is2dArray(
  arr: MyType[] | [MyType[], ...MyType[][]],
): arr is [MyType[], ...MyType[][]] {
  return Array.isArray(arr[0]);
}

if (is2dArray(values)) {
  values;
  //^? const values: [MyType[], ...MyType[][]]
}

TypeScript Playground

Leave a Comment