4 ms·
`Record` is a dangerous type, and I would recommend against it. The problem is that it assumes any key is valid and will return a value type. Example: type
by phailhaus 5y ago
`Record` is a dangerous type, and I would recommend against it. The problem is that it assumes any key is valid and will return a value type. Example:
type Tips = Record<string, TipObject>
const tips: Tips = {}
tips["hello"] // TipObject, but you actually get undefined
It's better to define a Dictionary type like so:
type Dictionary<K extends string | number | Symbol, V> = Partial<Record<K, V>>
Then to use:
type Tips = Dictionary<string, TipObject>
const tips: Tips = {}
tips["hello"] // TipObject | undefined
That way, you're always forced to check for existence, and you never accidentally attempt to access properties on `undefined`.
- throwaway284534 5y agoYou’re right that this is really easy to mess up, especially when defining an array index e.g. const todos: string[] = [“walk dog”]; todos[123].toUpperCase() // error! IMO non constant (as defined by TypeScript) arrays should’ve been automatically assigned a union type with `undefined`, which can also be a fix for Records too: type Tips = Record<string, TipObject | undefined>
- jakelazaroff 5y agoYou’re looking for the noUncheckedIndexAccess compiler option: https://www.typescriptlang.org/tsconfig#noUncheckedIndexedAccess https://www.typescriptlang.org/tsconfig#noUncheckedIndexedAc...
- jakelazaroff 5y agoIt’s not true that Record will result in a type where any key is valid. If you pass in a primitive like string, then of course any string will be valid. That’s not Record’s fault; what you’re doing is essentially creating an index signature [1]. If you pass a more restrictive type in as the key, it works as expected: type Tips = Record<“foo”, TipObject>; const tips: Tips = {}; // error, needs key “foo” tips["foo"]; // fine tips["bar"]; // error, no key “bar” in tips It’s worth mentioning that this isn’t just an issue with objects. For example, by default, the index type on arrays is unsafe: const arr: number[] = []; const first: number = arr[0]; // actually undefined, but typescript allows it If you do need an index type and want to account for undefined keys, the idiomatic way is the noUncheckedIndexAccess compiler flag [2], which will automatically make any index property access a union with undefined. [1] https://www.typescriptlang.org/docs/handbook/2/objects.html#index-signatures https://www.typescriptlang.org/docs/handbook/2/objects.html#... [2] https://www.typescriptlang.org/tsconfig#noUncheckedIndexedAccess https://www.typescriptlang.org/tsconfig#noUncheckedIndexedAc...
- deleted 5y ago[deleted]
- deleted 5y ago[deleted]