Makla Makla - 3 months ago 29
TypeScript Question

TypeScript - typeof array of union types

If I have array of union I can check for typeof value this way:

//case 1
function something1(a1: Array<number | string | boolean>)
{
for (const v of a1)
if (typeof v === "number")
v; //v is number
else if (typeof v === "boolean")
v; //v is boolean
else
v; //v is string
}


If I have union of array I could do it the same way:

//case 2
function something2(a1: Array<number> | Array<string> | Array<boolean>)
{
for (const v of a1)
if (typeof v === "number")
v; //v is number
else if (typeof v === "boolean")
v; //v is boolean
else
v; //v is string
}


but I want to avoid checking for type inside loop:

//case 3
function something3(a1: Array<number> | Array<string> | Array<boolean>)
{
if (a1.length === 0)
return;
if (typeof a1[0] === "number")
a1; //should be number[]!! but it is number[] | string[] | boolean[]
if (typeof a1[0] === "boolean")
a1; //should be boolean[]!! but it is number[] | string[] | boolean[]
if (typeof a1[0] === "string")
a1; //should be string[]!! but it is number[] | string[] | boolean[]
}


but a1 is not recognised as number[] or string[] or boolean[].

But this makes sense. Since all items in array are the same type. Is it possible to achieve that?

I am using TypeScript beta 2.0.

Answer

With type guards:

function something3(a1: Array<number> | Array<string> | Array<boolean>) {
    if (a1.length === 0)
        return;
    if (isArrayOfNumbers(a1))
        a1[0].toExponential();
    if (isArrayOfBooleans(a1))
        a1[0].valueOf();
    if (isArrayOfStrings(a1))
        a1[0].indexOf('abc');
}

function isArrayOfNumbers(arr: number[] | string[] | boolean[]) : arr is number[] {
    return arr.length > 0 && typeof arr[0] === 'number';
}

function isArrayOfBooleans(arr: number[] | string[] | boolean[]) : arr is boolean[] {
    return arr.length > 0 && typeof arr[0] === 'boolean';
}

function isArrayOfStrings(arr: number[] | string[] | boolean[]) : arr is string[] {
    return arr.length > 0 && typeof arr[0] === 'string';
}
Comments