Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better Object.entries #167

Closed
wants to merge 7 commits into from
Closed

Conversation

PCOffline
Copy link

@PCOffline PCOffline commented Sep 6, 2023

Intro

This type changes the behaviour of Object.entries to return more specific types:

Object.entries({ a: 1, b: 2, c: 3 } as const);
// Before change: [string, 1 | 2 | 3][]
// After change: (["a", 1] | ["b", 2] | ["c", 3])[]

Object.entries({ a: true, b: 'string', c: { field: 1 } } as const);
// Before change: [string, true | "string" | { readonly field: 1; }][]
// After change: (["a", true] | ["b", "string"] | ["c", { readonly field: 1; }])[]

Object.entries([1, 2, 3] as const);
// Before change: [string, 1 | 2 | 3][]
// After change: [number, 2 | 1 | 3][]

Caveats

  • In TypeScript 5.0, the function would automatically transform any object or array into a read-only object using the const keyword for more specific results. Therefore, the difference between the results of Object.entries in TypeScript 5 would be even bigger, since the as const part would be omitted.
    In earlier versions, for specific results, the as const assertion needs to be added to inputs.
  • The order of the elements in the result of Object.entries cannot be relied on, therefore a union of tuples is returned instead of a deterministic tuple (i.e. (["a", 1"] | ["b", 2])[] and not [["a", 1], ["b", 2]])

@PCOffline
Copy link
Author

Todo: update readme

@mattpocock
Copy link
Collaborator

Please read the section in the readme that describes why we won't make this change.

@mattpocock mattpocock closed this Sep 6, 2023
@PCOffline
Copy link
Author

Alright, didn't see it in the GitHub Readme. Makes sense though

@tyilo
Copy link

tyilo commented Dec 14, 2023

Please read the section in the readme that describes why we won't make this change.

@mattpocock This seems to be gone from the README. Could you add the note here?

@tyilo
Copy link

tyilo commented Dec 14, 2023

Found it:

Rules we won't add

Object.keys/Object.entries

A common ask is to provide 'better' typings for Object.keys, so that it returns Array<keyof T> instead of Array<string>. Same for Object.entries. ts-reset won't be including rules to change this.

TypeScript is a structural typing system. One of the effects of this is that TypeScript can't always guarantee that your object types don't contain excess properties:

type Func = () => {
  id: string;
};

const func: Func = () => {
  return {
    id: "123",
    // No error on an excess property!
    name: "Hello!",
  };
};

So, the only reasonable type for Object.keys to return is Array<string>.

@PCOffline
Copy link
Author

PCOffline commented Dec 14, 2023

Bruh this issue was closed 3 months ago how'd you even find it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants