Search code examples
typescriptfor-looptypesiteratornumber-formatting

How to type the iterator of a for loop as numeric string?


Even though I have declare the type for the iterator i as NumericalString, TypeScript still throws this error:

Argument of type 'string' is not assignable to parameter of type 'type'.deno-ts(2345)

I understand that because when test(i) is called, there is no way for the IDE to know that i is indeed a numerical string. So how to overcome this? I don't want to convert it to number manually.

type NumericalString = `${number}` | number

function test (i: NumericalString) {
    console.log(i, typeof i)
}

for (const i in ['a', 'b', 'c']) {
    test(i) 
}

Note: I need the loop to be for...in, not for...of. In the actual data, I have a pair of arrays, say arr1 = ['John', 'Mary', 'Tom']; arr2 = ['cat', 'dog', 'mouse']. So that I can do for (i in arr1) {console.log(arr2[i])}


Solution

  • Edit

    Now that's not a TypeScript typing problem anymore. for...in always returns the key as a string. Obviously, a string is neither assignable to number nor "${number}". A possible workaround is using Object.keys() manually, map all keys to a number and iterate over the values using for...of

    type NumericalString = `${number}` | number;
    
    function test(i: NumericalString) {
      console.log(i, typeof i);
    }
    
    for (const i of Object.keys(["a", "b", "c"]).map(Number)) {
      test(i);
    }
    

    Original Answer

    The problem here is that for...in loops over the keys. You want to use for...of instead to loop over the values of e. g. ["1", "2", "3"]. However, I'm not sure about why you would want to pass an item of ['a', 'b', 'c'] (an array that clearly consists of strings) to a function with a parameter of type NumerialString.

    type NumericalString = `${number}` | number;
    
    function test(i: NumericalString) {
      console.log(i, typeof i);
    }
    
    const items: NumericalString[] = ["1", "2", "2"];
    
    for (const i of items) {
      test(i);
    }