Skip to content

refactor: Change return type of Object.entries from [string, V] to [K, V] #31

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

Closed

Conversation

ushironoko
Copy link

Currently, the return value of Object.entries is [string, V], which is weakly typed when extracted by subsequent map, etc.
Therefore, we propose to return [K,V] so that the type of the key can be inferred.

However, we do not consider other detailed use cases. If it is not appropriate, please CLOSE.

Supplemental

I ran the test and it mocked up loudly🤯.

@graphemecluster
Copy link
Contributor

This is not true. Object.entries ignores symbol keys, and returns strings even for numeric keys, as they are actually strings.
Maybe K extends symbol ? never : `${K}` would be a good solution, but this may cause issues related to variance.

@ehoogeveen-medweb
Copy link

FWIW, I'm using the following locally:

type KeyToString<K extends number | string | symbol> = keyof {
	[key in K as key extends string ? key : key extends number ? `${key}` : never]: unknown;
};

declare global {
	interface ObjectConstructor {
		keys<K extends number | string | symbol, V>(o: Record<K, V>): KeyToString<K>[];
		entries<K extends number | string | symbol, V>(o: Record<K, V>): [KeyToString<K>, V][];
		values<K extends number | string | symbol, V>(o: Record<K, V>): V[];
	}
}

It works well for my code, but there might be edge cases that I didn't consider.

@ehoogeveen-medweb
Copy link

The above seems to not work with the TypeScript 5.4 beta because the resulting keys still include number. I'm not sure whether that's a bug in the beta or not, but as a workaround we can intersect with string:

type KeyToString<K extends number | string | symbol> = string &
	keyof {
		[key in K as key extends string ? key : key extends number ? `${key}` : never]: unknown;
	};

@ehoogeveen-medweb
Copy link

Though actually, I can't remember why I made it that complicated in the first place. This also seems to work just fine:

type KeyToString<K extends number | string | symbol> = K extends string ? K : K extends number ? `${K}` : never;

@ehoogeveen-medweb
Copy link

I came across some issues with the current implementation and the above suggestions in #40. Here's a version that works for those cases too:

type KeyToString<K extends PropertyKey> = K extends string ? K : K extends number ? `${K}` : never;

interface ObjectConstructor {
  keys<K extends PropertyKey, V>(o: [K, V] extends [never, never] ? never : Record<K, V>): KeyToString<K>[];
  values<K extends PropertyKey, V>(o: [K, V] extends [never, never] ? never : Record<K, V>): V[];
  entries<K extends PropertyKey, V>(o: [K, V] extends [never, never] ? never : Record<K, V>): [KeyToString<K>, V][];
}

@ushironoko
Copy link
Author

Closed due to long term neglect. sorry.

@ushironoko ushironoko closed this Sep 19, 2024
@ushironoko ushironoko deleted the fix-object-entries-return-type branch September 19, 2024 05:32
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.

3 participants