简体   繁体   中英

typescript class constructor inferring types based on args of its function as argument

Sorry if the title is not very clear, but I don't know how to phrase my problem better.

I have a Process class:

class Process {
  readonly fn: Function;
  readonly parameters: any | any[]; // doing sth here to have the types inferred based on `fn` args
  nextMessage: Message | null;

  constructor(fn:Function, parameters: any|any[]){
    this.fn = fn;
    this.parameters = parameters;
  }
}

when instantiating a new Process Object:

function doTask(task: string){
  console.log(`doing ${task}`);
}
const message = new Process(doTask, "Something");

I want to have type check on the parameter that i pass to Message constructor to match the type on the function argument. like, in the code above, if I pass a number instead of string, I want to get an error.

The simplest way is to have a type parameters that represents the parameter types of the function as a tuple:

class Process<T extends any[]> {
  readonly fn: (...args: T) => any;
  readonly parameters: T; // doing sth here to have the types inferred based on `fn` args
  
  constructor(fn: (...args: T) => any, parameters: T){
    this.fn = fn;
    this.parameters = parameters;
  }
}

function doTask(task: string){
  console.log(`doing ${task}`);
}
const message = new Process(doTask, ["Something"]);

Playground Link

For this purpose you have the type Parameters:

class Process<F extends Function> {
  readonly fn: F;
  readonly parameters: any | any[]; // doing sth here to have the types inferred based on `fn` args
  nextMessage: Message | null;

  constructor(fn: F, parameters: Parameters<F["apply"]>) {
    this.fn = fn;
    this.parameters = parameters;
  }
}

It does exactly what you would expect, extracting the parameter types.

It's implemented like this:

/**
 * Obtain the parameters of a function type in a tuple
 */
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM