5 ms·
> the moment I use Object.entries ... the key has been widened to string This is correct behavior though, and what you propose would be wrong. The type isn’t n
by nawgz 4y ago
> the moment I use Object.entries ... the key has been widened to string
This is correct behavior though, and what you propose would be wrong. The type isn’t narrowed. Type U satisfies type T when the keys of U are a superset of the keys of T, so long as the keys map to the correct value-types in the intersection of (keyof T) and (keyof U)
This is because the only time extra keys are outlawed is when you instantiate an object of type T and explicitly declare it as a T. I can link if you need but this is an important subtlety which is why Object.entries returns string instead of keyof T, and it’s not borne of MS/TS developer laziness
- Jacqued 4y agoYou’re right about how it works today but it seems to me this is an odd choice to make. Why not enforce object types? Could they add a strictness flag that lets objects actually be type safe and enables related functions to work out of the box? For me this stuff is a regular pain point as you end up typecasting at every call site :(
- nawgz 4y ago> Why not enforce object types? It would be incredibly painful to write idiomatic JS with constant narrowing required and would lead to huge performance issues. Imagine you write some generic sort capabilities, sorting by label, createdDate, etc., and then you declare some types interface SortableByLabel { label: string } interface SortableByCreatedDate { createdDate: Date } ... Then you implement a method function sortByLabel(a: SortableByLabel, b: SortableByLabel) { ... } I've written enough, I think you can see how easily this works today and how painful and un-performant it would be to do this if you had to narrow your objects or constantly write extra info into your types to allow them to not enforce narrowing, and then there's a whole can of worms around your "widen"-able object types being illegal to functions that require exact types, ... Instead you can just write arrays... interface MyInterface { key1: Type1; key2: Type2; ... } const myKeys:Array<keyof MyInterface> = [ 'key1', 'key2', ... ] as const; function operatesOnKeys(object: MyInterface) { // don't use Object.entries... myKeys.forEach((key) => { object[key]; // TS is happy, and bonus: // this will be type checked later if MyInterface changes }); } I think TS has some issues but this isn't one of them.