Type Transformations Workshop (9 exercises)
solution

Compare and Return Values with Extends and the Ternary Operator

The first thing we need to do is add a type argument to YouSayGoodbyeAndISayHello to turn it from a static value into a function.

Now that we're receiving the T, we add a check to see if it extends hello. If it does, return goodbye. Otherwise, return hello:

Think of the extends keyword as checking how what we pass in compares to what we provide.

If we pass a random string into YouSayGoodbyeAndISayHello, it won't be the same as "hello" so we'll end up with "hello" being returned:

Hovering over Example shows us:

Conditional types are immensely powerful, and are where TypeScript becomes less about "annotations you add to your JS" and more like its own meta programming language itself.

Note: As of TypeScript version 4.8 the only way to do conditionals is with the ternary operator, though they can be nested.

Transcript

[0:00] This type now, this type helper, YouSayGoodbyeAndISayHello, the first thing that we need to do is add a type argument to it. This type argument turns this from a static value into a function. Now, this T is the thing that we're receiving. We do a check here.
[0:19] This extends keyword, we're going to talk about this a lot, but this might be one of the first times that you're seeing this in the course. If it's the first or second time, then what this is doing here is we're checking if T extends hello, if it can be compared to hello. If it can be compared to hello, then we return goodbye. Otherwise, we return hello.

[0:43] Let's say, "type Example." We say, "YouSayGoodbyeAndISayHello hello." What we get back is goodbye because we've triggered this branch. It's passing this check here.

[0:55] If we put in something random here, then does it extend hello? Does it match that pattern? No, it doesn't, so we end up with hello as the return type. We can change this to blah, blah, blah, blah, blah. We'll get back blah, blah, blah, blah, blah.

[1:11] This is really intriguing. This lets us do really complex type logic within this function structure. We can pass in different things and return different things based on input. This is going to feel pretty overwhelming right now, but this drives a lot of the really, really powerful stuff you can do with TypeScript.

[1:33] This conditional type here is immensely powerful. It starts to turn TypeScript from just some annotations that you can add to your JavaScript to its own meta programming language itself. This is what starts creating the Turing completeness of TypeScript that you might have heard about.

[1:53] This very simple concept is really integral to what makes TypeScript powerful. Yes, unfortunately, the only way to do this right now, as of TypeScript 4.8, is to do this ternary syntax. You can nest these ternaries. We may look at this later. It is pretty ugly to look at.

[2:14] Hopefully, you've understood all of the constituent parts here. We have a type function with the arguments here, with the check here, with the if-true and the if-false here.