#Need Help: Struggling to make KeyPath & ValueAtPath types work

12 messages · Page 1 of 1 (latest)

wide moon
#

I'm creating two types KeyPath<Object> and GetValueAtPath<Object, Path>.

KeyPath<Object> — takes an object type and generates an array type of all possible elements to reach a certain value in the object. Think "address.city" in a type:

type Person {
  name: string;
  address: {
    street: string;
    city: string
  }
}

...but instead of a string, you use an array: ['address', 'city']. Why? I want to support symbols since object keys can be symbols.

GetValueAtPath<Object, Path> — takes an object type and path, and should return the type of the value at that path.

I'm trying to fix the error on line 8 in this index.ts file.

There's another utility type there, DeepBoolean<Object>, which takes an object type and returns another type that expects the value of every property of Object to be optional boolean.

On line 8 in the linked file above, I'm getting this:

Argument of type 'boolean' is not assignable to parameter of type 'GetValueAtPath<DeepBoolean<Input>, KeyPath<DeepBoolean<Input>>>'.

...and I have been unable to spot what I'm doing wrong.

Any leads will be appreciated.

StackBlitz

Next generation frontend tooling. It's fast!

#

Need Help: Struggling to make KeyPath & ValueAtPath types work

full nimbus
#

The argument is defined as: value: GetValueAtPath<T, P>
The path value you provide is of type: P = KeyPath<DeepBoolean<Input>>
So overall the value you provide is expected as: GetValueAtPath<DeepBoolean<Input>, KeyPath<DeepBoolean<Input>>>

why do you expect it to match with boolean? The type of path you provide need to be "const enough" for your type to extract boolean out of it, but currently its just a wider type GetValueAtPath<DeepBoolean<Input>, KeyPath<DeepBoolean<Input>>>

#

also even if the expected type is specific enough to extract values from it, it could also be a DeepBoolean which is more than just a simple boolean

wide moon
wide moon
#

@full nimbus I now understand the problem.

full nimbus
# wide moon <@488324471657332736> I now understand the problem.

Great, just a tip: You dont have to and most of the time shouldnt replicate what your runtime code does on a type level. Often its better to mainly focus on the types API you provide. Especially if youre building a library. TS is not the fastest when you grow, esp. with this type complexity. And ts go should not be an excuse to write slow code (esp as I suspect that those types are magnitudes slower than a more simple alternative).

wide moon
#

sigh, you're probably right

#

thanks for your help. I really appreciate you taking the time to look at this

full nimbus
atomic otterBOT
#
goosydev#0

Preview:ts type Path<T, K extends keyof T = keyof T> = K extends | string | number ? T[K] extends Record<string, any> ? T[K] extends ArrayLike<any> ? | K | `${K}.${Path< T[K], Exclude<keyof T[K], keyof any[]> >}` : K | `${K}.${Path<T[K], keyof T[K]>}` : ...

wide moon
# atomic otter

Yeah I definitely considered this. In fact, it's what I went with initially. But then I wanted to FULLY support ALL Standard Schema's supported property keys, and that's why I have broken crap 😂