#Conditional type of `get` util

14 messages · Page 1 of 1 (latest)

haughty shell
#

I would like to be able to have a simple get function defined as: const get = (key, obj) => obj[key]; I'm struggling to annotate it properly so that it properly infers that get("x", {"x": 2}) is a number. So far I have:

function get<K extends PropertyKey, T extends object>(key: K, obj: T): K extends keyof T ? T[K] : undefined {
    const hasKey = (obj: T, key: PropertyKey): key is keyof T => key in obj;
    if (hasKey(obj, key)) return obj[key];
    return undefined;
}

But I have 2 errors:

  1. Type 'T[K & keyof T]' is not assignable to type 'K extends keyof T ? T[K] : undefined'.
  2. Type 'undefined' is not assignable to type 'K extends keyof T ? T[K] : undefined'

How should I be able to fix them and could you help me to understand this error messages? Here is a link to the playground.

rapid grail
wraith dirge
#

I had an idea, I'm not sure if it covers every possibility or not

midnight hillBOT
#
webstrand#0

Preview:ts function prop<T extends object, K extends PropertyKey>( key: K, obj: T & {[P in K]?: undefined | T[P & keyof T]} ): typeof obj[K] { return obj[key] } ...

wraith dirge
#

but it at least solves all of the problems you mentioned and every test case I can think of right now

#

now, if you wanted to return something other than undefined when the key is missing, I don't know that's possible with this trick

haughty shell
haughty shell
#

!resolved

#

@wraith dirge any idea why conditional type K extends keyof T ? T[K] : undefined does not work here? 🤔

wraith dirge
#

a more intelligent compiler could execute some special cases, but typescript isn't there yet

#

so my personal rule of thumb is: if the generic function has a conditional return type, expect to be forced to use as assertions or ignore compiler errors.