TypeScript 是否可以在数组标记为 “as const” 后经过操作后继续推断其确切值?

huangapple go评论52阅读模式
英文:

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

问题

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]?

英文:

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]?

答案1

得分: 1

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[].

英文:

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

type ConvertedNumbersToStrings&lt;Arr extends readonly any[]&gt; = {
    [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&lt;Arr extends readonly any[]&gt;(arr: Arr)
    : ConvertedNumbersToStrings&lt;Arr&gt;
{
    return arr.map(x =&gt;
        typeof x === &quot;number&quot; ? x.toString() : x
    ) as ConvertedNumbersToStrings&lt;Arr&gt;;
}

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

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

huangapple
  • 本文由 发表于 2023年2月27日 04:04:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/75574706.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定