Home > front end >  Is it possible to create dynamic types that can be reused in another method?
Is it possible to create dynamic types that can be reused in another method?

Time:01-26

have the following service:

class ExperimentService {
 //...
 public __items: string;

 public uploadExperiments<Payload extends Dictionary<ExperimentItemType[]>>(payload: Payload): asserts this is this & Record<"__items", keyof Payload> {
  // ...
 }

 public getItem<Name extends typeof this.__items>(name: Name) {
  // ...
 }
}

const expirementService: ExperimentService = new ExperimentService();

expirementService.uploadExperiments({ mock: [...] });
expirementService.__items; // type mock

expirement.getItem; // getItem<Name extends string>() string is displayed, but it should be mock

is there any possibility to get dynamic types in getItem method?

CodePudding user response:

You could add a type parameter to ExperimentService that defaults to string (to keep the current behavior) and that you can use when you assert the type of this to change all places the type parameter is used:

class ExperimentService<K extends string = string> {

    public __items!: K;

    public uploadExperiments<Payload extends Dictionary<ExperimentItemType[]>>(payload: Payload):
        asserts this is ExperimentService<keyof Payload & string> {
        
    }

    public getItem<Name extends K>(name: Name) {
        
    }
}

const expirementService: ExperimentService = new ExperimentService();

expirementService.uploadExperiments({ mock: [""] });
expirementService.__items; // type mock

expirementService.getItem; // Names extends "mock"

You could also infer the type base on the type of the instance getItems is getting called for, but this involves adding an extra type parameter to the function:

class ExperimentService {
    public __items!: string;

    public uploadExperiments<Payload extends Dictionary<ExperimentItemType[]>>(payload: Payload):
        asserts this is this & Record<"__items", keyof Payload> {
    }

    public getItem<TThis extends ExperimentService, Name extends TThis['__items']>(this: TThis, name: Name) {
    }
}

const expirementService: ExperimentService = new ExperimentService();

expirementService.uploadExperiments({ mock: [""] });
expirementService.__items; // type mock

expirementService.getItem("mock");  /// mock

Playground Link

  • Related