Home > Mobile >  How do we force Typescript to use the default generic argument type here?
How do we force Typescript to use the default generic argument type here?

Time:12-24

const EventKeys = {
  openItem: 'openItem',
  changeActiveItem: 'changeActiveItem',
  selectionToggled: 'selectionToggled',
} as const

type EventKeys = keyof typeof EventKeys


class Test<Evmt>{

    subscribe<CurrentEeventKey = Evmt>(arg:CurrentEeventKey){
      //here the type is being picked up correctly
      console.log(arg)
      return arg
            //     ^?

  }
}


const t1 = new Test<EventKeys>
//     ^?const t1: Test<"openItem" | "changeActiveItem" | "selectionToggled">

const abc = t1.subscribe('11223')
// here the type param should give error since it should take up constructor value here
//     ^? const abc: "11223"

t1.subscribe<'11223'>('11223')
// but here the type param should not give error since it should take the supplied value here


I tried passing the argument and setting a default value. I wanted the function to have the generic type value picked up from the default value passed by the constructor call.So that it doesn't need to be defined again. But when provided on function call it should take that type Inside the function inference works and type is correct

CodePudding user response:

class Test<Evmt> {
    subscribe<CurrentEeventKey extends Evmt>(arg: CurrentEeventKey) {
      //here the type is being picked up correctly
      console.log(arg)
      return arg
    }
}

You have set the default generic value when you need extends

CodePudding user response:

To force TypeScript to use the default generic argument type for the Test class, you can use a generic constraint on the CurrentEeventKey type parameter. This will ensure that the type of the CurrentEeventKey type parameter is always the same as the Evmt type parameter passed to the Test class.

Here is an example of how you can do this:

const EventKeys = {
  openItem: 'openItem',
  changeActiveItem: 'changeActiveItem',
  selectionToggled: 'selectionToggled',
} as const

type EventKeys = keyof typeof EventKeys

class Test<Evmt> {
  subscribe<CurrentEeventKey extends Evmt = Evmt>(arg: CurrentEeventKey) {
    // here the type is being picked up correctly
    console.log(arg)
    return arg
  }
}

const t1 = new Test<EventKeys>()
//     ^? const t1: Test<"openItem" | "changeActiveItem" | "selectionToggled">

const abc = t1.subscribe('11223')
// here the type param should give error since it should take up constructor value here
//     ^? const abc: "11223"

With this change, the type of the abc variable will be inferred as an error, since the '11223' value is not a member of the EventKeys type.

CodePudding user response:

Use two overloads,
A default one, with inherited argument One without generic inference, defaulting to void Playground

import { F } from 'ts-toolbelt'
class Test<Evmt>{
    subscribe<CurrentEeventKey extends Evmt>(arg: CurrentEeventKey): CurrentEeventKey;
    subscribe<CurrentEeventKey = void>(arg: F.NoInfer<CurrentEeventKey>): CurrentEeventKey;
    subscribe<CurrentEeventKey = Evmt>(arg: CurrentEeventKey) {
        //here the type is being picked up correctly
        console.log(arg)
        return arg
        //     ^?
    }
}
  • Related