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

ObjectEntry has poor behaviour for partial types #48

Open
cefn opened this issue Dec 18, 2023 · 0 comments
Open

ObjectEntry has poor behaviour for partial types #48

cefn opened this issue Dec 18, 2023 · 0 comments
Labels
unconfirmed bug Needs confirmation

Comments

@cefn
Copy link

cefn commented Dec 18, 2023

The ObjectEntry type is intended to help with consuming the pairs from Object.entries. It is currently implemented as...

export type ObjectEntry<T> = { [K in keyof T]: [K, T[K]] }[keyof T];

However its behaviour is not ideal in practice when consuming entries from a partial type (that has optional values) owing to...

  • the use of keyof which is systematically too broad
  • allowing through a partial value type, when optionality makes no sense for a entry which has been found in an object

In particular, undefined values and undefined entries are permitted through.

Expected behavior

ObjectEntry should reflect possible values from an object with optional properties (which is to say if there is an entry, it is populated, and that entries themselves cannot be undefined).

You can see an errored case of the current implementation, and a fixed implementation TypedEntryOf in the playground at https://www.typescriptlang.org/play?ts=5.3.2#code/C4TwDgpgBA8gRgKwgY2AUQHbAE4gDwAqAfFALxQDeUA2gNJQCWGUA1hCAPYBmUBAugC4atADS86fPlAC+1Npx78A3AFgAUOtCRe4CABNa7GF0IlyBKBAAewCBj0BnKAAUAhtmANXAGzxMuENhQAEokAPxQABTBljZ2jiEoHNh6fhgBQaJQAK4YLBgcAO4Y4VD0QhgQAG6BAJRQFdWBqmpa0AS6epg4IMamZJTCjMwdkAZGJsSCwmLBEACO2QzY+qYSUrKj+oa9k0R8LZq6Lt6ulcAAMhwcLNlgAxTqUFAAFhDe3hxhQgDkhcnePQ-FrPF4Mb5QH4AW3cDmB6mkhzUyA4GAcwCgnxudyEzlO5yu2Pu5EealB70+v3+2EBPxET1eDF+MOwcPpamkUFcThRaOASLaUDQVlcULA3ggWy6WFwxgGUu6spMbW4mOutzARBaAHptc8AHphdRHbTC0XiiDwJCoRUgAZWlDoGX4FU8LEarXqXUGo0aNRAA

image

Actual behavior

Undefined values creep in at multiple levels

Steps to reproduce

See provided playground

Suggested solution?

A preferred implementation is shown below...

type TypedKeyOf<T> = T extends Partial<infer R> ? (R extends Record<infer K, unknown> ? K : never) : never;
type TypedEntryOf<T> = { [K in TypedKeyOf<T>]: [K, Required<T>[K]] }[TypedKeyOf<T>];

What version of emery are you running?

Latest at the time of writing

Demo

type ObjectEntry<T> = { [K in keyof T]: [K, T[K]] }[keyof T];

type PlanetLookup = {
  hello?: 'world';
  hi?: 'mars';
};

const lookup: PlanetLookup = {
  hello: 'world',
  hi: 'mars',
} as const;

type ExampleObjectEntry = ObjectEntry<typeof lookup>;
//  ^? // ["hello", "world" | undefined] | ["hi", "mars" | undefined] | undefined
@cefn cefn added the unconfirmed bug Needs confirmation label Dec 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
unconfirmed bug Needs confirmation
Projects
None yet
Development

No branches or pull requests

1 participant