Is it possible for typescript to continue to infer the exact values of an array marked "as const" after it goes through an operation?

Advertisements

Say I have this array:

const myArray = ["foo", 3.14, true] as const;

Typescript will infer that this array is:

readonly ["foo", 3.14, true]

So it knows exactly what the array is.

I’m trying to increase my knowledge of typescript, and I’m trying to figure out if it’s possible to perform a generic operation on this array as const and preserve typescript’s inference of these values.

For example, is it possible to write a function in typescript called convertNumbersToStrings() that accepts any readonly array as an argument and outputs another readonly array where, if I pass my as const array, typescript can infer that the result is: ["foo", "3.14", true]?

>Solution :

Yes, it is possible (thanks to @Blackhole for correcting my Sunday night brain failure).

type ConvertedNumbersToStrings<Arr extends readonly any[]> = {
    [Index in keyof Arr]:
        Arr[Index] extends number ? `${Arr[Index]}` : Arr[Index]
}

TS playground here

Mapped tuples tend to need a little help and the implementation is rough, but you’ll get a result:

function convertNumbersToStrings<Arr extends readonly any[]>(arr: Arr)
    : ConvertedNumbersToStrings<Arr>
{
    return arr.map(x =>
        typeof x === "number" ? x.toString() : x
    ) as ConvertedNumbersToStrings<Arr>;
}

const myArray = ["foo", 3.14, true] as const;
const out = convertNumbersToStrings(myArray);
// typeof out = readonly ["foo", "3.14", true]

Without the return type annotation, out‘s type is inferred as any[].

Leave a ReplyCancel reply