Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript infer the callback return type in type constructor

I want to write a type constructor for a function which receives a type S and a function from S to another type then applies that function on the S and returns the result:

// This works but it's tied to the implementation
function dig<S, R>(s: S, fn: (s: S) => R): R {
  return fn(s);
}

// This works as separate type constructor but I have to specify `R`
type Dig<S, R> = (s: S, fn: (s: S) => R) => R;

// Generic type 'Dig' requires 2 type argument(s).
const d: Dig<string> = (s, fn) => fn(s); 

So how can I write a Dig<S> type constructor which infers the return type of the passed fn argument without me specifying the R?

like image 735
Sam R. Avatar asked May 12 '26 03:05

Sam R.


1 Answers

As of TS3.4 there is no support for partial type argument inference, so you can't easily have the compiler let you specify S but infer R. But from your example, it doesn't look like you want to infer R as some concrete type, but allow it to remain generic so that the return type of fn can be whatever it wants to be when you call d().

So it looks like you really want this type:

type Dig<S> = <R>(s: S, fn: (s: S) => R) => R;

This is sort of a "doubly generic" type, in the sense that once you specify S you've still got a generic function dependent on R. This should work for the example you gave:

const d: Dig<string> = (s, fn) => fn(s);

const num = d("hey", (x) => x.length); // num is inferred as number
const bool = d("you", (x) => x.indexOf("z") >= 0); // bool inferred as boolean

Okay, hope that helps. Good luck!

like image 88
jcalz Avatar answered May 14 '26 19:05

jcalz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!