'How do you infer the integer type from a modulus operation in TypeScript?

Contrived example of code:

const someArray = ['a', 'b', 'c', 'd', 'e'];
const remainder = someArray.length % 3;
const someObject = {
  'key0': 'value0',
  'key1': 'value1',
  'key2': 'value2',
};

const value = someObject[`key${remainder}`]; // TypeScript complains with:
// Element implicitly has an 'any' type because expression of type '`key${number}`'
// can't be used to index type '{ key0: string; key1: string; key2: string' }'.
// ts(7053)

My understanding is that because JavaScript only has numbers as a concept, TypeScript is doing the safe thing of assuming that the length of the array could be a non-integer number. How can you inform TypeScript that the values being used to calculate remainder are integers and thus the result is constrained to 0, 1, and 2?



Solution 1:[1]

You can cast someArray.length % 3 to 0 | 1 | 2 so TS would know the range of numbers (TS playground):

const someArray = ['a', 'b', 'c', 'd', 'e'];
const remainder = someArray.length % 3 as 0 | 1 | 2;
const someObject = {
  'key0': 'value0',
  'key1': 'value1',
  'key2': 'value2',
};

const value = someObject[`key${remainder}`];

Another option is to cast key${remainder} explicitly as a key of someObject (TS playground):

const someArray = ['a', 'b', 'c', 'd', 'e'];
const remainder = someArray.length % 3;
const someObject = {
  'key0': 'value0',
  'key1': 'value1',
  'key2': 'value2',
};

const value = someObject[`key${remainder}` as keyof typeof someObject];

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1