March 11th, 2024 × #TypeScript#JavaScript#Web Development
TypeScript Interview Questions - STUMP’d
Wes and Scott quiz each other on advanced TypeScript features and syntax in a segment they call 'Stumped'.
Transcript
Scott Tolinski
Welcome to Syntax. On this Monday, hasty treat, we are going to be playing a mini round of stumped where Wes and I try to stump each other with questions on various tech. Now today, we are going to be doing a quick round of TypeScript Stumped, which I'm slightly not looking forward to because Russ has been working on a long course on TypeScript, and I just use it casually. So, I mean, I use it to develop my things, but I'm, I'm no, like, you know, TypeScript genius ESLint so. Weeds. Yeah. Yes. So be prepared for,
Wes Bos
potentially 4 big red x's on this side of the table. Node not I'm not gonna do, like, how do you infer a record conditionally? Because, like, that's a whole another level of of TypeScript.
Wes Bos
This is more just like user features that that we'll be talking about today, but a couple couple little nuggets. We're gonna do 4 questions each. So, hopefully, between all of the 8 things, you can learn a thing or two.
Scott Tolinski
Yeah. And, if you are, not using TypeScript, you're probably gonna have bugs. And your software we don't want your software to have bugs. Well, I use TypeScript, and I have bugs. If you're using TypeScript, your software probably has bugs. Yeah. It you know, this is the nature of things, and that's why you need a service like Sentry to help you out. This podcast is, presented by Sentry.
Scott Tolinski
It's a really awesome software for just making sure your applications run smooth, whether that's speed, size, bugs, user experience.
Scott Tolinski
Yeah. Perf. So yeah. Perf?
Wes Bos
Sanity? We had we had some rage clicks the other sorry. Let me don't stop the ad read yet, Scott. Let me tell you about my rage clicks the other day. We had Yes. Somebody, on the website, and I got a email. And they had a couple rage clicks and then a dead click. And Essentri does this detection of when somebody clicks on something and there's no noticeable change in the UI, like nothing happened, that's a dead click. And then if someone does that repeatedly, that's a rage click. And it shows it in the playback, and it was really interesting because you can watch. It's a 15 minute progress of somebody. So, obviously, there's something something going on there that, they were obviously trying to click something, and it wasn't working. And I was able to play it back and kinda see what was going on with the user and and figure out what actually caused this specific error. So check it out. Anyways.
Scott Tolinski
Yeah. No. No. I think that's important because you know what? Let's just talk about Sentry here.
Century detects rage clicks and dead clicks to identify frustrated users
Scott Tolinski
One nice thing about Sentry is that they get developer stuff. So, like, whether that is the concept of a rage click or their fact that your most viewed pages, if they're slow, they give them a user misery Scott. Like, how upset your users are that this page, which is accessed frequently, is slow.
Scott Tolinski
So I just love that stuff. So century.ioforward/ syntax.
Scott Tolinski
Sign up. If you, if you ever talk to anybody at Century, tell them that you heard about it from Syntax because, hey, that makes us look really good.
Wes Bos
By the way, speaking of related, our landing page, centric.i forward slash syntax. That's a new landing page. Looks super good.
Wes Bos
Yeah. Check it out. Enough of that. Let's get into some questions. You wanna go first?
Scott Tolinski
I would love to go first. Alright. I'd love to go 1st. Here's here's my first question for you. How do you combine string literal types?
Wes Bos
Oh, combine string literal types.
Scott Tolinski
You may give a what a string literal type is for folks too. I mean, you don't have to. But
Wes Bos
A a string literal type is a, when you use back ticks in TypeScript, and you wait. Are we talking about that? Now now you're confusing me of of what they are here.
Scott Tolinski
A a string literal type is when a type is a literal string.
Scott Tolinski
So instead of, like, in, you might use, you know, here are the type states is equal to active Okay. Inactive.
Scott Tolinski
But let's say you wanted
Wes Bos
some root in some, like, suffix or something, and you wanted to combine some or yeah. I I thought you were asking about which what was the answer, which is the template string types. I believe that is the answer. So you use back ticks.
Wes Bos
And then inside of the back ticks, you can take 2 different, strings, or you can take a union of 2 different strings and combine them together, and it will then create a union of every single permutation. So if you have red, green, blue, 1, 2, 3, that's gonna kick out all 9 combinations of, like, red dash 1, red dash 2, red dash 3, blue dash 1, blue dash 2, etcetera, etcetera. So combining those together is extremely Sanity.
Wes Bos
And let me tell you a little kinda cool tip that you can do is you can also just type straight strings into those backticks as well. So if you have a let's say you have an invoice string and you wanna make sure that it starts with I n v. What you could do is you could say I n v and then just put a number, like, dollar sign curly bracket number inside of there, and it will say, alright. This is a type that starts with I n v and then has a number at the end, which is is really, really handy, when you have, like, things like IDs or invoice numbers where it's just it's a string. Right? But it's a more specific string.
Scott Tolinski
Yeah. It's neat.
Scott Tolinski
Not even something I've used. So I I saw that. I was like, oh, what's wrong here is fine. Ain't that funny how sometimes when like, I panicked. I panicked there. And
Wes Bos
sometimes that happens when somebody uses a word for something that you you haven't used before or you're thinking about it in a different way, and
Scott Tolinski
that that's stressful, especially when you're in an interview Wes you're already stressed out. You could well, that's the whole thing. You your brain can work into all these types of ways Wes I'm saying, like, a string literal type. And you Node, obviously, what a string literal type is, but it's not like that connection doesn't always happen right away with, like, what that word is or with what the technique is. And and sometimes words are give things importance to
Wes Bos
Yeah. Things that make them seem a little bit more complex than they are. My question for you next is what is a TypeScript generic, and why would you use 1?
Scott Tolinski
Yeah. Well, a TypeScript thank you for this, question, Wes, because it's one I can answer.
Scott Tolinski
A a TypeScript and I'm gonna do my best to answer it. A TypeScript generic is if you think about the word generic, it's it's kind of like it's not a specific definition for something. It's a generic definition.
Scott Tolinski
However, what you're saying is Wes you're defining something as a generic, you don't necessarily know what it is, but you wanna say that it's a thing. A common example might be you have a function that always returns the same type as its input.
Scott Tolinski
So you would say whatever that function is that accepts a generic, and it will return the same type of that generic. Or perhaps, you know, maybe it's returning a promise of that same Yes. Data structure or something. Like a like a database function. Nailed it. Like, a good example would be, like,
Wes Bos
a a database query. Right? You could you could query for users or you could you could query for shows.
Wes Bos
And you're not gonna make 2 2 functions, 1 for users, 1 for shows. You're just gonna have a generic query, and then you pass a generic, to that. You say, alright. I'm going to query for a user, and that will allow you to both have type safe input as well as returned value.
Scott Tolinski
Yeah. And sometimes there's metadata on there. Sometimes you're not even returning the same thing, but you need Yeah. To pick parts of it out. Yeah. All kinds of ray, partials, part of it. Good. That's a good example. Thank you. Next question here. How do you write a conditional type? Oh, that's a good one. I know. I'm sorry. I tried to go hard on yours because I know you were going deep on TypeScript.
Wes Bos
You use the it's it's kind of like a alright.
Wes Bos
A conditional type is using the same I'm gonna have to say the word turn ternary ternary.
Wes Bos
Ternery.
Wes Bos
Where ternery.
Wes Bos
And you you do your condition.
Wes Bos
Usually, that is something like something extends this. So if if this generic can extend a string, so if a type of string, then question mark, you return your type. Otherwise, colon, you return the other value.
Scott Tolinski
Nailed it. Good. Yeah. Those of you out there I mean, the big thing is ternary. I mean, that that's kind of it.
Scott Tolinski
But it is often
Wes Bos
like what you said. If some type extends another type, show 1. Otherwise, show the other. Yeah. And, like, when would you possibly want that? Well, sometimes you are looping over a bunch of keys in a specific type, and you want to check.
Wes Bos
Like, for example, I just talked about, invoice strings that start with I n v. What you could do there is you could check if the invoice string is overlaps with the type of I n v and then a number. And if it does, then you can do things like strip off the I n v dash if you want to, or you could in that case, you wanna do something different to that type, capitalize it, lowercase it, otherwise, return a different value.
Scott Tolinski
Yes. Nailed it. Alright.
Wes Bos
Here we go. I have a function that returns a promise of a user, but there are no types provided for that function, and you cannot generate the types.
Wes Bos
You cannot just write out the type yourself. How would you generate a TypeScript type for the return value of that function in TypeScript? Let me know if you want me to say it again.
Scott Tolinski
Yeah. So let me you you have it's returning a user that users, like, coming from a database or something. It's not just like an object.
Wes Bos
Yeah. You have a well, the the function itself is an asynchronous function, so it turns a promise, and then it returns a value, which is which is a user. But there's no there's no user type. So how without manually creating the user type yourself, how would you get a user type from that function?
Scott Tolinski
Oh, yeah. I mean, you could just let TypeScript infer it. You could hope hope that the library provide it. Yeah.
Wes Bos
Well types in That that's half of it. But how do you Okay. It it is inferred, but how do you store that inferred value in a actual type that you can then Oh, okay. Use somewhere else in your application? Okay. Can't you just say type user equals infer and then the the
Scott Tolinski
value you're trying to infer from?
Wes Bos
Close.
Wes Bos
Okay. The answer is brackets.
Wes Bos
Two parts. First of all, you use type of and then the name of the function without calling it. And what that will do is type of will give you the TypeScript type for the entire function signature, so the inputs, the parameters, as well as the outputs.
Wes Bos
And then you wrap that in a return type, which then takes the whole function signature and and makes it just down to the return type.
Wes Bos
And but that's still wrapped in a promise.
Wes Bos
So then you wrap that again in a utility function called awaited, which will then give you the actual return value. So if you ever have functions that don't export types, the way that you can get access to those types of the functions are type of and then do a whole bunch of dancing with return type and a weighted or if you want the arguments to that function, you you just use, the arguments,
Scott Tolinski
utility function. Really? Yeah. I I guess, you know, the only utility functions I use are, like, promise. Awaited, I haven't used awaited before. So that's to get the values from something that returns a promise?
Wes Bos
Yeah. It it basically unwraps a promise. So if you ever have a type Yeah. Like like a function that returns a promise that of a user, and you're like, I don't care about the promise Yarn. I just care about the user. You can unwrap the promise with awaited.
Scott Tolinski
Hey. By the way, on a totally unrelated topic, did you see there was a Twitter thread going around somewhat recently about callbacks versus promises in JavaScript and performance, and it was, like, massive.
Wes Bos
Really? Because of the event loop?
Scott Tolinski
I I didn't dive deep into it. I just saw, like, here's some interesting, benchmarks on using promises versus using callbacks.
Scott Tolinski
Maybe we should have gone or I think the the premise was maybe callbacks weren't that bad.
Scott Tolinski
I thought that was really interesting. I'll have to find it because, I thought, you know, not something that people talk about. We just started using promises because they're easier. But
Wes Bos
Yeah. I'm not going back to to callbacks. Oh, yeah. I I see the blog post. We'll link it up in the show notes here. Nice. Wow. Good thing. That's really cool. I bet I bet it has to do with the fact that when you await something, it sticks it at the end of the event loop, and that is possibly an issue. I don't know. Like Yeah. Have I ever had a problem Wes, like, oh, yeah. That awaiting the promise. No. It's the 15 meg image that I'm, trying to download or the, like, blocking, synchronous code that I'm running on the main thread instead of in a service worker. Those are usually my issues. Yeah. Maybe though. Maybe performance is of paramount, and you need to
Scott Tolinski
I'll eventually hit something like that. Yeah. Next one for you. I think this one's maybe a little bit easier. How do d.ts files work?
Wes Bos
Ah, good.
Wes Bos
So d.ts files are different than TypeScript files in that you cannot put JavaScript in them. You may only put TypeScript definitions inside of them.
Wes Bos
So d dot t s files are generally generated from a code base, that needs to be shipped. So if you are an author of a library on NPM, you write your code base in JSDoc or in TypeScript.
Wes Bos
Generally, what happens is you you generate those d dot ts files, and you ship them, alongside your repo or in a TypeScript, and then somebody can include those via their TS config.
Wes Bos
And then TypeScript essentially knows about these types that can be, used without having to import them directly from each of those values. So pretty Sanity. Also, really handy for declaring modules that do not have types for them. So, for example, the other day in the syntax code base, we used a markdown plug in to add IDs and links to every single show notes heading. So if you somebody's like, hey. I wanna link to part of the show notes, and there's no there's no IDs on your h three tags.
Wes Bos
So, we went in. I added a plug in, and everything worked great, except there was no, types for that thing. And I went into the GitHub repo. There's no types anywhere, so I had to go figure out what were the types for that, and and then I just threw them into there's a file in our code base that we can put types into.
Wes Bos
I threw them into a d dot ts file, and that and then it I basically said, declare module, whatever the name of the module was, and I wrote all the types for it. And, then TypeScript picked them up for that module.
Wes Bos
Sick. Yeah. Perfect.
Wes Bos
Ideally, no no d.ts files, with JSR. Well, JSR will generate them for Npm, but, ideally, we just consume the TypeScript directly, and we don't need d dot ts files. Yeah. I just got my JSR invite. I'm stoked to start using it.
Wes Bos
Name one difference between a type and an interface in TypeScript.
Wes Bos
Oh, okay. I got it. This one is intentionally a little bit like, because almost never matters.
Scott Tolinski
Almost never matters, but you can extend an interface, and you can't extend a type.
Wes Bos
Yeah.
Scott Tolinski
I mean, you can extend a type with the ampersand. Right? Yes. Okay. You're right. But you can extend with The extends word. The keyword. Yes. Okay.
Wes Bos
Yeah. So with types and interfaces, both of them can be extended.
Wes Bos
But the way that you extend them with types is with the ampersand, and the way you extend in interfaces with the extends keyword.
Wes Bos
Do you have anything that can only be done with a type or an interface?
Scott Tolinski
Nothing beyond just, like, mundane syntax things that I I don't I don't I don't know what you're looking for. I should know this, but I I just use types, really. Yeah. Yeah. It doesn't
Wes Bos
that's what I keep saying in my courses JS it probably doesn't matter unless you're gonna hit something where, oh, I can't do it this way, and then it'll switch to the other. So there's a handful of of different ones.
Wes Bos
Interface merging is probably the most
Scott Tolinski
common and useful one. That's what I was thinking when I said extending. I was thinking merging that you're asking. Okay. Okay. So you you did get it right then. Wes, I I didn't say extending or merging. I yeah.
Wes Bos
So with interfaces, you can declare an interface multiple times, and they will fold into each other. Meaning that you can declare interface window and put something on the window, and that's not gonna overwrite all of the other window methods on there.
Wes Bos
This is really handy with like, I'm using some Cloudflare stuff right now to run Next. Js, and they have their environmental variables, and then they have some some Cloudflare type.
Wes Bos
And if you wanna add on your own environmental variables on top, you don't wanna over overwrite theirs. You just wanna add yours into that. Right? So using an interface ESLint that case is the only way to sort of fold those in, because if you were to write a type, it would simply overwrite the the existing type. So that's probably the most common one.
Wes Bos
And then the other the only one of the big ones for types is that a type alias can only be done with a type. So if you say, like, type whatever equals, in a lot of cases, you can't do those with with interfaces.
Wes Bos
Same with, like, your your merging example. Right? You can't do the you can't merge strings together within interface.
Scott Tolinski
Right. Yes.
Scott Tolinski
Here's the last question I have for you, and this Node I think is also made more difficult by its name. But Okay. What is a triple slash directive, and why would you use them?
Wes Bos
Yes.
Wes Bos
The triple slash directive is something that is hardly ever used. In fact, I Node the conscious decision to not include this in my course.
Wes Bos
It's for referencing external type files inside of a TypeScript file or a JavaScript file where you cannot import those types.
Wes Bos
So you will only ever see these in it's like a a thing from, like, 8 years ago. And in most cases, it's a thing from before Wes, before we had ECMAScript modules in TypeScript. So it was a way to reference where the d dot ts files lived without having to import them into your TypeScript file, because sometimes people aren't aren't using TypeScript files. You'll all you'll often see them in, like, compiled, like, iffy code that is output by a bundler, but
Scott Tolinski
I'm gonna say probably never in your life will you need to write 1 manually. Have you ever had to write 1? Nope. And, that's that is it is the the point, which is one of the reasons why I added that why would you use it. Because I know if you gave that answer, oh, it's referencing ambient types or or, those type of things, people would say, well, why don't I use this? And the answer is, you don't really use them, now now that we have PSM.
Wes Bos
Yeah.
Wes Bos
Alright. Last question we have here.
Wes Bos
What is a TypeScript record, and what is it used for?
Scott Tolinski
A type what is a TypeScript record? I don't know. It's for scratching.
Scott Tolinski
I am a record.
Scott Tolinski
I don't know exactly what a record is by by word record, but I probably know what it is by concept.
Scott Tolinski
So no. I don't I don't have an answer for you here, but I I know I'm gonna go, woah. I shoulda have known that. Yeah. Wes you say A TypeScript record is a Wait. Wait. Wait. Let let me let me try it. Let me try it. Yes. I think it's Let's have it.
Scott Tolinski
Okay.
Scott Tolinski
It's it's for defining, it's it's a utility wrapper for defining an object.
Scott Tolinski
Yep.
Scott Tolinski
Yeah.
Scott Tolinski
Where you don't know the contents of it necessarily.
Scott Tolinski
You well, not maybe not that you don't know the contents of it. Yeah. Okay. I'm getting worse. So I'm that meme.
Scott Tolinski
Yeah.
Scott Tolinski
Oh, this is great. Yeah.
Wes Bos
Sorry.
Wes Bos
Sorry. I was not confusing you.
Scott Tolinski
Man, I'm trying to think because I there are situations where I have needed to reach for a record instead of defining as an object. Maybe perhaps you don't know how many things are in the object.
Scott Tolinski
You could say, no. You can do that with an object too. I don't know.
Wes Bos
A a TypeScript record is a utility method, you Node that, for defining an object type Yep. Where the you know the type of the keys and of the values. So, very commonly, you will have a union of keys. So, like, I want the key to be small, medium, large, and then the the values will be a T shirt or a hoodie. Right? So you'll say, I want a record of the keys are small, medium, large, and the the the values are going to be type of T shirt or a type of hoodie.
Wes Bos
And then that is just a shorthand for rather than creating an object and using the square bracket keys Wes you say key in whatever, you loop over them and and and generate it for you. It's just a a handy dandy utility type.
Scott Tolinski
I'm gonna tell you what. I almost always do the actual object notation instead.
Wes Bos
No reason why. That's just how I've done it. Just just Warp first it. You understand? Yeah. Yeah. It's like I said, it's it's just a utility method that that lives on on top of the actual TypeScript. So you can type it out yourself as well, if you wanted to. And in some cases, you you do need to type it out because if you our record does not allow you to mark keys as, optional.
Wes Bos
So if you if you want them to be optional, you either have to type it out yourself or you wrap it in like a, another utility function.
Wes Bos
Or if you wanna do if you wanna add additional properties to a record after you've looped over everything, then you would need to do that yourself.
Wes Bos
Beautiful.
Wes Bos
Yeah. Jeez.
Wes Bos
Yeah. Some some tricky, tricky things in there. So, hopefully, you learn a thing or two. This is Scott and I put ourselves out there, to be embarrassed about these things so that you will the listener will learn a thing or two.
Scott Tolinski
Yeah. I think it's important to know that, like, hey. Somebody asked what a triple slash directive is or whatever. Even though Wes got that question right, you might have heard that and be like, I never heard of that in my entire life. And you know what? That's cool. You don't have to be an effective TypeScript developer and know all the little nuances. But it is fun to, you know, dive deep and and get those types of quizzes going and and get your brain juices going on, like, what's what.
Scott Tolinski
I mean, I write TypeScript every day. So if you're out there and you're Yeah. You're like,
Wes Bos
I don't know what any of this stuff is. Hey. That's how it goes. Right? You gotta learn it. Yeah. And even just, like, having this stuff rolling around your noggin so that Wes do hit these problems, you'll say, ah, those guys talked about that. What was that? You know? You can look it up and figure out how it works.
Wes Bos
Alright. That's it. Thanks, everybody, for tuning in. We will catch you later.
Wes Bos
Peace.