#Why second generic type not being inferred by related arg when explicitly set first generic type?

26 messages · Page 1 of 1 (latest)

grand robin
#

normally generic types can be inferred by their related args,
thing1, inferred correctly;
while in thing2, i explicitly set the first type parameter, and its key is inferred as "any", which is the default type of the second type parameter;
why? is this a fact?
i don't recall this being mentioned in typescriptlang.org.

type CreateThingOption<
  Value = any,
  Key extends string = any,
> = {
  key: Key;
  serialize?: () => Value;
}

function createThing<
  Value = any,
  Key extends string = any,
>
(option: CreateThingOption<Value, Key>) {
  return option
}


let thing1 = createThing({
  key: '1',
})
type Key1Type = typeof thing1['key'] // "1"


let thing2 = createThing<string>({
  key: '2',
})
type Key2Type = typeof thing2['key'] // any. WHY???
unique falcon
#

you can't partially infer generics, you have to provide all or none.
the any you're getting is from the default value that you've specified.

#

you should avoid any for reasons like these, they become "infectious" in a way

#

generally function generics don't need defaults.

grand robin
unique falcon
#

if you omit the defaults you'll get the error for it

#

also, the handbook is not documentation.

#

it's a guide to get started, but it doesn't include everything

grand robin
#

does this rule make any sense?

grand robin
unique falcon
#

from this server, i wouldn't have encountered the situation on my own

#

it's not so much a rule as a limitation

#

ah, found the thing

#

!:%partial%

blissful martenBOT
grand robin
#

👀

signal halo
#

I don't know if this will do much good or not meet your requirements, but if you change the order of the generics you can get the string value

type CreateThingOption<
    Key extends string = any,
    Value = any,
> = {
    key: Key;
    serialize?: () => Value;
}

function createThing<
    Key extends string = any,
    Value = any,
>
    (option: CreateThingOption<Key, Value>): CreateThingOption<Key, Value> {
    return option
}


let thing1 = createThing({
    key: '1',
})
type Key1Type = typeof thing1['key'] // "1"


let thing2 = createThing<string>({
    key: '2',
})
type Key2Type = typeof thing2['key'] // any. WHY???```
grand robin
signal halo
#

if you want to receive '2' as type you can either remove the string or pass directly '2', it cannot return another value since you are telling it that it is a string type directly

eternal ledge
#

Is Key used in more than one place inCreateThingOption?

#

Actually, I'm confused what the purpose of manually specifying what () => Value should be even though you are not providing it. Are you mutating the object afterwards?

#

This feels like an XY problem, if you can show how you are intending on using the types, maybe we can provide better alternatives.

grand robin
#

i'm just curious about why. wanted to get a solid explanation.
no actual intent just found this strange while playing with generics.
you don't feel strange at all?

eternal ledge
#

It is mildly inconvenient in some rare cases but I haven't ran into many of those.

#

Both TS and C# are designed by the same person, and I'm not sure why it's designed that way, but I guess it's not big enough of a problem that neither language has decided it's worth fixing yet.