The Art of Type Arguments 9 exercises

Make a Generic Wrapper for a Function

Consider this makeSafe function. It takes in a function, then it returns a wrapped version of that function that can either return type: 'success' with a dynamic result or type: 'failure' with an error that gets thrown.

const makeSafe =
(func: unknown) =>
...args: unkn

Loading exercise


0:00 In this exercise, we have a function called makeSafe. MakeSafe, what it does is it takes in a function and then it returns a wrapped version of that function that can either return type success with a dynamic result or type failure with an Error, which is the error that gets thrown.

0:22 What we can see here is we should be able to return the result with a type success on a successful call.

0:28 MakeSafe, this is not going to error, and so results here should be type of result number, or rather, it's fine for it to be this discriminated union type. It shouldn't know whether it's going to succeed or fail, but it should have number in this slot.

0:44 We should also return the error on a thrown call, so this result type failure Error, this is probably going to work, except that result here should be typed as a string. Currently it's typed as unknown here, so there's a little bit of basic generics work for you there.

1:04 Also, it should properly match the function's arguments, too. Currently, makeSafe in here, we can pass it a, number, b, string, and it just returns them like this because currently the args here are unknown, you can pass any arguments here, so this one should error and this one should error.

1:24 You've got quite a bit of a job to do here because you need to somehow represent a generic that represents the function. Again, we're inside the art of generics, so you might be thinking, "OK, at what level do I want to be representing this at?"

1:40 You've also got to capture that and then stick it in all of the right places, make sure the result is properly typed to make sure that the arguments are properly typed. Good luck.