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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to construct type for "Object having path P"? #159

Closed
cjol opened this issue Dec 4, 2020 · 3 comments
Closed

How to construct type for "Object having path P"? #159

cjol opened this issue Dec 4, 2020 · 3 comments

Comments

@cjol
Copy link

cjol commented Dec 4, 2020

馃 Question

I'm trying to write a curried "select" function which plucks a value from inside a given object. The type for the non-curried version looks like this:

declare const selectPlain: <T extends object, P extends Array<A.Key>>(
  item: T,
  ...path: P
) => O.Path<T, P>;
const strVal = selectPlain({ a: { b: '' } }, 'a', 'b');

For the curried version, the best I've come up with is this:

declare const selectCurried: <P extends Array<A.Key>>(
  ...path: P
) => <T extends object>(item: T) => O.Path<T, P>;
const selectFooBar = selectCurried('foo', 'bar');

What I don't like about this is the T extends object generic. Because of this selectFooBar will appear to accept any object. I really want to end up with

const selectFooBar : <T extends {foo: {bar: any}}>(item: T) => O.Path<T, P>;

To do that I think I need to construct the type {foo: {bar: any}} from ["foo", "bar"]. Is that possible?

Search tags, topics

#typescript #path #get #select #curry

@millsp
Copy link
Owner

millsp commented Dec 4, 2020

Hey @cjol, yes this is very easy to achieve. We have Object.P modules that allow operating on objects at a Path. So you are looking for Object.P.Record https://millsp.github.io/ts-toolbelt/modules/_object_p_record_.html

@cjol
Copy link
Author

cjol commented Dec 4, 2020

Thanks, I was sure there would be a solution! For completeness, here is my final solution:

declare const selectCurried: <P extends Array<A.Key>>(
  ...path: P
) => <T extends O.P.Record<P, any>>(item: T) => O.Path<T, P>;
const selectFooBar = selectCurried('foo', 'bar');
const str = selectFooBar({ foo: { bar: 'hello' } });
// @ts-expect-error
const innerVal = selectFooBar({});

@cjol cjol closed this as completed Dec 4, 2020
@millsp
Copy link
Owner

millsp commented Dec 4, 2020

Glad I could help, have a nice day.

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

No branches or pull requests

2 participants