Search code examples
typescripttypescript-types

can I declare a type of an array literal?


In my typescript code, I have this fragment:

pairs.forEach(([n, s]) => {
  console.log(n * 3, s.toUpperCase());
});

I want to inline "pairs" variable. I know I can do it this way:

([[3, "three"], [5, "five"]] as [number, string][]).forEach(([n, s]) => {
  console.log(n * 3, s.toUpperCase());
});

But I don't like it, because now my code became worse. Before inlining, compiler was verifying that each element of the array is a pair of a number and a string - so, for instance, this code does not compile:

const pairs: [number, string][] = [[3, "three"], [5, "five"], ["seven", 7]];
pairs.forEach(([n, s]) => {
  console.log(n * 3, s.toUpperCase());
});

But after inline, a type of my array is not declared. Instead, I use a type assertion, which tells the compiler to ignore what it thinks the type is and take my word for what this type is. So now compiler does not verify that each element of the array is a pair of a number and a string. So, for instance, this code compiles, and only fails in runtime:

([[3, "three"], [5, "five"], ["seven", 7]] as [number, string][]).forEach(([n, s]) => {
  console.log(n * 3, s.toUpperCase());
});

Can I somehow have both things - both have this array inlined and tell compiler what is its type? Can I somehow declare a type of an array literal?


Solution

  • I think you can't really do it automatically.

    In let pairs = [[3, "three"], [5, "five"]], the type of pairs is auto-detected as (string | number)[][] rather than as ([number,string][] )
    That's why after inlining, it doesn't behave like you wished, it'll just use the (string | number)[][] that it inferred.

    It seems that the auto-detect tries to detect a variable-length array rather than a tuple whenever it has the chance.
    So, let x = [3,4] is detected as number[] rather than [number,number]
    And let pair = [3,'three'] is detected as (string|number)[] rather than [number,string]

    enter image description here