简体   繁体   中英

How do I define and call a generic function parameter in Typescript?

I'm looking for the one-argument typesafe equivalent of Function.prototype.call in Typescript.

This does not work, because F is missing the proper constraint (perhaps):

function call<F,A>(f: F, arg: A) {
  return f(arg);
}

Thus, Typescript complains "This expression is not callable. Type 'unknown' has no call signatures."

How do I make F callable? How do I manage call to have the return type of F ?

As you said, you'll need to add a constraint so it's callable. One option may look like the following:

function call<F extends Function,A>(f: F, arg: A) {
  return f(arg);
}

Generic Constraints: https://www.typescriptlang.org/docs/handbook/generics.html#generic-constraints .

If you wanted to provide stronger type safety one approach may look like the following.

type Parameter<T> = T extends (arg: infer T) => any ? T : never;


function call<F extends (arg: any) => any>(f: F, arg: Parameter<F>): ReturnType<F> {
  return f(arg);
}

const fn = (input: number): number => input * 2;

const result = call(fn, 2) // Valid
const result2 = call(fn, "2") // Argument of type '"2"' is not assignable to parameter of type 'number'.(2345)
const result3 = call(fn, false) // Argument of type 'false' is not assignable to parameter of type 'number'.(2345)

const badFn = (input: number, options: {}): number => input * 2;

const result4 = call(badFn, 2) // Argument of type '(input: number, options: {}) => number' is not assignable to parameter of type '(arg: any) => any'.(2345)

This defines a more strict constraint for F , saying it must be a function that accepts only one argument. The argument is then inferred from that function. You could also use Parameters<F>[0] since Parameters is a utility type provided by Typescript. ReturnType is another utility type to infer the return type of F which can be used as the return type of call .

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