#infer type in a function with two args

27 messages · Page 1 of 1 (latest)

warm osprey
#

so i have a function type like (simplified variant)

type get = <MyObj extends Record<string, unknown> = Record<string, unknown>, T extends keyof MyObj>(key: T) => Environment[T]

but this just doesn't seem to work - whatever way i try to turn it.

so basically the function should be used like

const value = get<{ example: string }>('example') // < should only allow 'example' as key
// ^ should have value of type string

so i want that the user passes a object type as first arg and the second arg should be inferred, but the inferring part doesn't work how i want it to

oak saffron
#

Your example only has one argument

#

Would this work? ```ts
type get = <T extends keyof MyObj>(key: T) => Environment[T]

fallen flax
#

I would guess you'd rather want something like

type get = <T extends keyof Environment>(key: T) => Environment[T]

but that seems too simple to give problems so I think there is some context missing here

warm osprey
#

@fallen flax @oak saffron but then the type for the object would need to be defined outside of that function

#

i want to pass that object type as first type argument to the function and then the argument of the function would be a key of that object and return the corresponding value

fallen flax
#

aaah

#

i see

#

sec

#

It's bad news btw

#

7 year old issue asking for the feature of some generic parameters being specified and some of them being inferred

#

So, afraid you just can't do that

warm osprey
#

:(

fallen flax
#

You could hack around it by using a useless function returning a polymorphic function:

warm jewelBOT
#
angryzor#9490

Preview:```ts
declare const get: <
MyObj extends Record<string, unknown> = Record<
string,
unknown

() => <T extends keyof MyObj>(key: T) => MyObj[T]

get<{example: string}>()("example")
get<{example: string}>()("exafmple")```

fallen flax
#

But that's giving up program semantics + performance for the sake a of a type convenience

#

which is a hard sell

warm osprey
#

any other workarounds? global types i guess?

fallen flax
#

for instance, or you could also do something like this:

#

no wait that's just the same but with an object inbetween:

warm jewelBOT
#
angryzor#9490

Preview:```ts
interface CoolOperators<
MyObj extends Record<string, unknown> = Record<
string,
unknown

{
get: <T extends keyof MyObj>(key: T) => MyObj[T]
}

declare const getOperators: <
MyObj extends Record<string, unknown> = Record<
string,
unknown

() => CoolOperators<MyObj>
...```

warm jewelBOT
#

@fallen flax Here's a shortened URL of your playground link! You can remove the full link from your message.

angryzor#9490

Preview:```ts
type Getter<MyObj> = <T extends keyof MyObj>(
key: T
) => MyObj[T]

declare const get: any

;(get as Getter<{example: boolean}>)("example")
;(get as Getter<{example: boolean}>)("exafmple")```

warm osprey
#

hm yeah, all of the workarounds pretty much suck thonk

fallen flax
#

yeah

warm osprey
#

i think - as there's no "nice solution" - i should probably close this thread