Skip to content

Issue when using object with Object.entries and Object.values #40

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
ehoogeveen-medweb opened this issue May 13, 2024 · 4 comments · Fixed by #42
Closed

Issue when using object with Object.entries and Object.values #40

ehoogeveen-medweb opened this issue May 13, 2024 · 4 comments · Fixed by #42
Labels
bug Something isn't working

Comments

@ehoogeveen-medweb
Copy link

TS Playground

As shown above, this overload included in better-typescript-lib cause an issue when applied to an object without a specified key or value type. The overload seems to match too eagerly, returning a type with never instead of falling through to the more generic call signatures.

Here's one way to fix it, although I don't know if it's the best fix: TS Playground

The same fix seems to work for Object.entries as well.

Note: This issue is unrelated to #31 (but maybe worth mentioning there)

@ehoogeveen-medweb
Copy link
Author

For posterity and to avoid having to check the playground, the problematic overloads are:

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

and the proposed fix:

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

@ehoogeveen-medweb
Copy link
Author

This might be a better fix, targeting object and wider types specifically:

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

@uhyo uhyo added the bug Something isn't working label May 13, 2024
@ehoogeveen-medweb
Copy link
Author

Hmm, it seems that object and any record with never-typed keys mutually extend each other:

type foo = object extends Record<never, unknown> ? true : false; // true
type bar = Record<never, unknown> extends object ? true : false; // true

so to be minimally invasive I guess we want something like

interface ObjectConstructor {
  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>): [string, V][];
}

so that records with never-type keys or never-type values still yield the expected result.

Putting it together with #31:

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][];
}

TS Playground

@uhyo
Copy link
Owner

uhyo commented Jul 16, 2024

A fix has been released as v2.8.0. Thank you for reporting!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants