Let’s start from the bottom line: there’s a simple alternative to typing Typescript functions, that’s more concise and logical than the Typescript’s “native” method. It makes use of a utility type, which I’ll call simply Function, that is easily defined:

type Function<A = any[], B = any> = (...args: A extends any[] ? A : [A]) => B;
view raw
Function.ts hosted with ❤ by GitHub

For example:

function minimumOf(fn: Function<number, number>, interval: [number, number]) {
		// Approximate/solve...

	// Works!
	const m1 = minimumOf(Math.sqrt, [1, 3]);

	// Argument of type '(x: number, y: number) => number' is not assignable to parameter of type 'Functiona<[number], number>'.
	const m2 = minimumOf(Math.pow, [1, 3]); 
view raw
Function-exmaples.ts hosted with ❤ by GitHub

Feel free to save it, and use it wherever you find it valuable!

There’s no hack behind this definition — it simply uses some of Typescript’s advanced features effectively:

  • At the heart of it all lies the types A and B — those are Generics, and they’re a popular (advanced) concept in object-oriented programming in many languages, Typescript included. To put it simply, A and B are wildcards, which adapt themselves to the given context (or to whatever you explicitly tell them to, if you do). They can be used to provide better enforcement in more complex or abstract cases, as well as a better programming experience, and are widespread in Typescript APIs and libraries. For example, for the fn parameter in the example above, A and B both become number types.
  • We make use of Typescript’s ability to infer tuple types as sets of function parameters. For example, if A gets the type [number, boolean], the compiler will interpret that as a function that receives two parameters — the first is a number, and the second is a boolean.


The better way to type functions in Typescript
1.10 GEEK