DEV Community 👩‍💻👨‍💻

Discussion on: The Record Utility Type in TypeScript

dailydevtips1 profile image
Chris Bongers Author

100% agree with you, just because we are Typescript we can't just leave things to it.
We should still validate everything.

Just one small question about your initial comment,
just because it handles the numbers as strings, is that really a concern though?

In most cases it's not really used anyway (just wondering why we should even care about that)

Thread Thread
peerreynders profile image
peerreynders • Edited on

just because it handles the numbers as strings, is that really a concern though?

On the surface no, because TypeScript tries to enforce consistent access with the declared type.

But it still leaves a JavaScript type coercion footgun in place:

const record: Record<string | number, string> = {
  0: 'zero',
  1: 'one',
  2: 'two',
};

const oldOne = 1;
const newOne = '1';

console.assert(record[oldOne] === 'one');
record[newOne] = 'newOne';
// Oops
console.assert(record[oldOne] === 'newOne');

// Meanwhile TS flags this as an error
// "This condition will always return 'false' since the types 'number' and 'string' have no overlap"
// Actually it returns `true` due to type coercion; TS just doesn't like it...
// console.assert(oldOne == newOne);

// ...because
console.assert(typeof oldOne !== typeof newOne);

// At least this works (ES2022)
console.assert(Object.hasOwn(record, 2));
console.assert(Object.hasOwn(record, (2).toString()));
Enter fullscreen mode Exit fullscreen mode

Similarly

const values = ['zero', 'one', 'two'];

const oldOne = 1;
const newOne = '1';
const anotherOne = '01';

console.assert(values[oldOne] === 'one');

values[newOne] = 'newOne';
console.assert(values[oldOne] === 'newOne');

console.assert(typeof oldOne !== typeof newOne);

console.assert(Object.hasOwn(values, oldOne));
console.assert(Object.hasOwn(values, oldOne.toString()));
console.assert(Object.hasOwn(values, newOne));
console.assert(!Object.hasOwn(values, anotherOne));
Enter fullscreen mode Exit fullscreen mode

So TypeScript being typed had an opportunity to clean things up at least for objects to restrict property keys to strings and symbols but existing JavaScript code bases sometimes use numbers as property keys (for convenience) and not supporting that could have hurt adoption.