Making TypeScript Stick

Intermediate Type Challenges: Q&A and IsTuple

Mike North

Mike North

Making TypeScript Stick

Check out a free preview of the full Making TypeScript Stick course

The "Intermediate Type Challenges: Q&A and IsTuple" Lesson is part of the full, Making TypeScript Stick course featured in this preview video. Here's what you'd learn in this lesson:

Mike answers student questions regarding how practical the type challenges are for everyday use of TypeScript and if ternary expressions with the extends keyword are the only way to do conditional types. A walkthrough of the last intermediate type challenge involving correctly typing IsTuple is also covered in this segment.


Transcript from the "Intermediate Type Challenges: Q&A and IsTuple" Lesson

>> I see that there are some questions from the class in chat. So Oscar asks, how practical are these typed challenges? He says, I can understand you will learn the ins and outs of the language better. But how often do you need to write these kinds of typed operations in your code or is the biggest benefit that this is about understanding how TypeScript works.

And that's exactly the point here. This I'm not suggesting that we do like CSV parsing in the TypeScript types themselves. What I'm suggesting is these kinda acrobatics give you the practice to where when you do encounter the occasional challenging thing you have to do in your real world code, by comparison, it will seem easy, right?

So if you need to run a marathon you have to do a lot of training beforehand. It's probably flood example because the marathon is more complicated. The bigger feet in that case but the idea is I want your everyday work and your everyday use of TypeScript to feel routine.

And part of that is sort of raising the ceiling on what you consider to be challenging or your ability to do things. So that's why we kind of get into these moral contrived things. It's about getting, turning back to that book that I talked about in the introduction of the course, making it stick.

It's about that desirable difficulty where you actually retain more, maybe thanks to this, you understand more about how template literal types work or how tuples work or rest and spread and how those work when it comes to types. And then when you do something a little bit more reasonable unless contrived in your own code.

Shouldn't seem pretty easy by comparison. All right Michael S in chat asks whether to ernary expressions with the extends keyword or the only way to do conditional type. So just refresh, that is something like this right? So yes, a conditional type is always like this. A extends, B question mark, if true colon if false, something like that.

Like there's no alternate syntax I'm aware of for doing this kind of thing. So it's, the only thing available. Okay, fantastic. So let's dig into this last of the medium difficulty challenges is tuple. So the idea here is we should be able to take a type puram T and evaluate out to true if thing is a tuple and evaluate out to false if it's not a tuple.

So, here use cases to look at Read Only arrays. Sorry read only tuples are regarded as tuples. Something that has a length property, which is one way we might try to determine whether something is array like. This is not a tuple and most importantly, an array is not necessarily a tuple.

So that should be false. Okay, does anyone have any ideas about how we could take a first pass of this? Maybe tackle one one piece of this problem? That's one of the things engineering is all about taking a bigger problem and then, breaking it down into smaller, more approachable chunks.

>> Extends, read only?
>> That's interesting. We've had to write, read only in these conditional types before. Maybe we need to do that. I'm not sure I have enough to write something on the screen though. I could write extends, read only.
>> T extends.
>> You're right.
>> Okay?

>> And then any array Okay, almost, so close well, I actually am not sure how close we are at this point. So, what we've identified here is array like things, right, now this would be great if we were implementing is array and this would have been true and we would be done.

>> Josefa extend extends array and. So [INAUDIBLE].
>> If it extends array, so it's in this branch here, right? Cuz if it's another tuple at all, sorry, if it's not an array like at all, we still wanna be false. So here, Like this.
>> What we're getting at?

>> It's really close, but we have different tests that light up now. So now it appears that all writable arrays are identified right? That's I'm just basing that based on this the fact that this tuple here fails our test. But this one here passes. Sorry, read readable arrays are what we're seeing.

Like this one's fine. I want to try something wacky here. Again, I do not have the solution in front of me. I know where to get it if I decided to give up. What about this? Nope. I need a question right here. Okay, so that's same as this cheat doesn't work.

That's the same as an array here. Okay, so we need to know if this is a array like, I have an idea here. So something that kind of makes, at least by the definition of our test cases here kind of makes the difference between an array and a tupple is finite length.

Right, finite like. So if we could measure the length of something like one of the cool things about infinity is what's infinity minus 1?
>> Infinity
>> Infinity and what 7 minus 1?
>> 6
>> So it stands to reason then if we pop one element out of this thing and compare its length links to the original length and they are equal we're dealing with an infinity what if we try that?

We infer the length earlier that's interesting yeah T square bracket length for sure. Yep that could work. Okay, so let's try this. I don't wanna leave a array of anys here, because that seemed to work for us. So we're gonna leave this false path here, it's false branch.

This is not even an array thing, and this is like array, or tuple. That's the path we're gonna go down. Okay, so we got to pop one element off. So we'll say, first Infer first and the rest again these are just type rounders. Sorry They're just angry because I haven't used them yet and we don't care about this first one.

Actually, we could do that. So, and then we could say does, I'm just gonna try it both ways cuz my brain hurts when I try to remember which direction the extends works. So rest length extends. So okay, let's make sure we do this in the same way. So T extends, so this is another conditional type here that we need for plucking out that rest.

And then we're gonna say it does the length of rest extend T Length. So this is, And if it does, then it'll say true, otherwise false. Let me do my indenting here just to get us back to where we can stay organized. So that's this this goes in here, this goes in here, I think we need one more false Okay I want to switch these just in case my comparison is the root of the problem here.

Interesting all right so here's what I like about this. These two cases down here. Are important. We have successfully evaluated a one length tuples to true, and we've successfully rejected an array of numbers. So I think our comparison thing is kind of working out here. Read only. So this makes me think we should add a read only somewhere.

Like what about here? Sorry Just try to feel out whether there's a constraint here, turns out there was. so I just made sure that anywhere I was using this extends thing cuz that's, again, it's like are greater than or equal to check but in a type world. We just had to make sure we had a read-only in both of these positions so that this test case here could appropriately fall through and hit the right path.

The way I would have identified this, by the way, this is the situation we were just in, I would have had this equivalent test case and said, hey, it's not about the tuple length or the member within it at all. It's the read only thing like I have a nearly identical case.

So that's where I would say, okay, something is a read only is falling down a path based on that. So I'd want to make sure that we have that there. That's how I sniff that out. All right, now, we're getting close here. Empty tuple, so this is a case where our strategy is not gonna work so well, because our whole basis for determining what's an array and what's a tuple is, measuring the length.

So I've got two ideas that popped into my head one is the cheap cop out which is another condition in here. Another which I think would be even worse, is instead of pulling something out of an array and comparing length, I could push something into an array. That actually doesn't sound so bad.

In fact, that makes this a lot simpler. That would be like this. And I don't have to infer anything I can use this dot spread thing. I can just push one more thing into the array. I'm gonna see if I can get us back there. And it works, wow, that was actually easier.

We got rid of a branch. So that's the approach here instead of saying, let's chop one item off of the array. I'm saying let's put something new in. So array of 6 become 7, 7 and 6 are not equal. Therefore we're dealing with a tupple. If it was infinity equals infinity in either direction, now we know we're dealing with an array.

And here we go. So this is the key insight here. I see that Oscar also looks like at the same time that I was thinking you about it. He suggested that we push into a tpple. So we effectively did that through the creation of a new tuple type that spread the existing one and then added one more thing, right?

So great. This is how you could tell tupple from an array. Now I want to add one more test case that may totally wreck thing. I'm just curious as to what will work at this point. This test case would have failed us. And I would argue this is kind of still a tuple.

It's a tupple of infinite length but we still sort of have opinions about the types of certain members at certain positions. It's not quite the same thing as like this here. I'm not going to go on this rant again. These are not the same thing T1 and T2.

T2 is an array T1 I have a different constraint on the first member of the thing compared to the rest of it. But for these test cases it worked
>> Does the concept of tuple exist outside of TypeScript or is it specifically a typed concept? Does that make sense?

>> The concept of tuples definitely exists outside of Typescript and in fact, TypeScript just in terms of when TypeScript was building this out, it had already been In Python and Erlang for ages, right? So and it exists in Duck typed languages as well, right? So you could create, I believe you can create a tuple in something like Ruby, where just like JavaScript, right, you just create an array, put whatever you want in it.

So there are different rules in different programming languages. So a lot of programming languages consider tuples to be immutable. So you create them you can use the equivalent of destruction assignment to pull things out of them but you're generally not I kind of be like putting something in the middle and changing its value.

They're kind of these sort of like cheap concise small collections of things, yeah. Scala uses them a lot as well. Good question. They're actually far less. We call them tuples in TypeScript, and they are but they're under the hood, they're just a race. So these are more similar to arrays than just about anywhere else that you would deal with a top.

But I'm gonna skip tuple to nested object just because of time constraints here. Feel free trying to solve this on your own. I'll show you in general type challenges where you can find answers. So there is tuple about the nested object see this one here. So if you click that you'll be able to jump to either take the challenge or checkout solution.

So In terms of your answer key this is where you could go.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now