741

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'.

or
Topic 0 00:00

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.

Topic 1 02:35

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.

Share