Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if an object is a readonly array in TypeScript?

How to do an array check (like Array.isArray()) with a readonly array (ReadonlyArray)?

As an example:

type ReadonlyArrayTest = ReadonlyArray<string> | string | undefined;

let readonlyArrayTest: ReadonlyArrayTest;

if (readonlyArrayTest && !Array.isArray(readonlyArrayTest)) {
  // Here I expect `readonlyArrayTest` to be a string
  // but the TypeScript compiler thinks it's following:
  // let readonlyArrayTest: string | readonly string[]
}

With an usual array the TypeScript compiler correctly recognises that it must be a string inside the if condition.

like image 544
miu Avatar asked Dec 31 '22 23:12

miu


2 Answers

Here's relevant issue in typescript.

Suggested workaround by @jcalz is adding overload to declaration of isArray:

declare global {
    interface ArrayConstructor {
        isArray(arg: ReadonlyArray<any> | any): arg is ReadonlyArray<any>
    }
}
like image 60
Aleksey L. Avatar answered Feb 09 '23 01:02

Aleksey L.


it should be like this

interface ArrayConstructor {
  isArray(arg: unknown): arg is unknown[] | readonly unknown[];
}

and test it in typescript

const a = ['a', 'b', 'c'];
if (Array.isArray(a)) {
  console.log(a); // a is string[]
} else {
  console.log(a); // a is never
}

const b: readonly string[] = ['1', '2', '3']

if (Array.isArray(b)) {
  console.log(b); // b is readonly string[]
} else {
  console.log(b); // b is never
}

function c(val: string | string[]) {
  if (Array.isArray(val)) {
    console.log(val); // val is string[]
  }
  else {
    console.log(val); // val is string
  }
}

function d(val: string | readonly string[]) {
  if (Array.isArray(val)) {
    console.log(val); // val is readonly string[]
  }
  else {
    console.log(val); // val is string
  }
}

function e(val: string | string[] | readonly string[]) {
  if (Array.isArray(val)) {
    console.log(val); // val is string[] | readonly string[]
  }
  else {
    console.log(val); // val is string
  }
}
like image 28
Kang Ming Chua Avatar answered Feb 09 '23 00:02

Kang Ming Chua