Rust for TypeScript Developers

Traits vs Interfaces



Rust for TypeScript Developers

Check out a free preview of the full Rust for TypeScript Developers course

The "Traits vs Interfaces" Lesson is part of the full, Rust for TypeScript Developers course featured in this preview video. Here's what you'd learn in this lesson:

ThePrimeagen compares interfaces in TypeScript with traits in Rust. Both interfaces and traits specify methods that should be found on the objects implementing them. Rust adds an extra level of abstraction by using the impl keyword to define the specific method implementation of the trait for a given struct.


Transcript from the "Traits vs Interfaces" Lesson

>> All right, so a little quick checkpoint. We've talked about iterators, enums, options, results and the borrow checker. We've kinda completed the very kind of like the basics of rust. How's everyone feeling about it? You generally have the idea in the sense that if I asked you to write a program, a small CLI program, you could probably accomplish that by googling and getting your way through it.

You have all the words in your head at least, right? You may struggle but you have ideas now, and that's what's important. That's the goal of this course is to get you so that you can struggle not just get you so you're just straight destroyed because when you first try rust you just get destroyed the first time through it's awful.

I did it for advent of code and it was just, the Buzz Lightyear one. I'd be like unwraps everywhere, right? It was just awful. All right, so traits we're gonna get into the last, like what I consider the last big concept of rust. The rest are gonna be the smaller and smaller, less complicated topics are slightly less complicated topics are still fairly complicated.

But I don't feel like they're as big other than macros, macros are terrifyingly large anyways, so traits they're like interfaces. You can define most of rusts behaviors such as addition, a quality checks, hashing parsing strings being displayed. All of this is gonna be via traits. Traits are like interfaces, but what you can do with them is much different than what you can do with interfaces in TypeScript.

What traits can be done cannot be done directly in JavaScript. You do not have the language capability to do that but you can do it differently that might work out. And so you could do it, it's just different. So first let's just jump off with some very simple trait stuff.

So what we're going to do is first in TypeScript we're gonna create a rectangle with a width, height, x, and y. And then we're gonna create a circle with a height, height, x, and y. With a radius X and Y, I would create them as classes because we're gonna add a couple methods to them.

So I know some of you hate classes, but just do that. So pretty straightforward. I'm gonna do it with you. So let's go class rectangle. It's gonna have a constructor and we're gonna have like a public wait public X number of Y, width, height. Look at that, rectangle, right?

There we go. We have them right there, fantastic. Could have made it private, whatever I don't, it is what it is. Let's do the same thing with circle. Let's do a circle. The only difference is, is that a circle has a radius, there we go. So if you don't feel like, by the way, I can see a lot of people aren't typing.

They look like they're focusing in hard. If you don't wanna to do the TypeScript part, at least try somewhat to do the Rust part, even though it's gonna be maybe a little painful. But I feel like it'd be really good, it'd be good for your soul so there we go.

Does that make sense everyone knows kind of what's happening here nothing confusing going on good. All right, let's go down here there we go wow I produced the same code, it's like I had this plan. All right, we could use types here but let's just face it. If you use just like a type and try to use a raw object, you're just being like a functional try hard at that point.

Trying to attach methods to objects like performance is terrible. Don't do that, just use classes if you're gonna do, go this way. So let's create an interface called area that has a singular method area. All right, let's go up to the top, go inter base area has a one function area that returns and number.

So that looks good, yeah, there we go. That's pretty, it's pretty good. There's that New York accent. I've never even been to New York. I don't even know where it's coming from. Just get so excited. All right, let's go back down. We got to add area to both circle and rectangle.

So some of the fun parts about JavaScript or TypeScript really, is you can go implements area. And then it'll give you an error, you can use code actions. You can implement it. You can jump down. You can do that. You can hit here and go return this dot width times this dot height.

Boom all right, fantastic. You've just done it. Or since TypeScript just does structural typing we can just copy this method, scroll on down here, and hit him with that old radius times radius times All right, there we go. Circle still implements the area interface, you just didn't specify it.

So, something kind of unique about TypeScript is that it's structural typing. Long as the structure of the thing you use matches the interface, you're that interface. If it walks like a duck and it quacks like an area, you got yourself a rectangle. Everyone knows that. All right, so pretty similar code.

I assume I don't have to explain any of that code, right. All right, so, what do you define every interface you state the method or property that requires, right? When you implement an interface, it must be done on the object at definition time is a very important concept.

At definition, you declare what I can do. All right, so I just want to state that, so look at that I declare rectangle, I also declare that I'm area interface and here. Okay, so let's do the exact same thing. Let's do it in Rust. So I'm gonna use float 64s.

So x will be defined as a float 64. So let's jump back into Rust. Let's praise the language. Struct Rect, I'm gonna call it Rect. The whole time I call it recting, I'm just going to call it rect because it's just so many extra letters to write. So here we go.

F64, y64, width 64, height 64, I'm gonna copy that out, do a circle, and, radius 64. And of course you have to have a main function, or else Rust will actually cry. And then there we go. Rust is no longer crying, we're all happy. This makes sense, right?

We've seen this enough times today that this is not too wild. So let's implement the area trait. Okay, I know it's a trait so this is unique. Remember a trait if you can recall from the very beginning is kind of like implementing the interface. I'm just gonna say the word trait area.

Function area, return out and F64 but remember, we need to tell area how it refers to the rectangle or circle. So I'm gonna say, hey, I need a read only reference to myself, that's all I need. I need a read-only reference to myself because I don't need to mutate anything.

I just need to be able to read the data and I should be able to calculate the area. Does that make sense? Okay, everyone's getting pretty pumped up. I'm getting pretty pumped up. All right, now let's implement, the area trait. Okay, so, if you remember, we go like this.

Implement Area for Rect. It's pretty straightforward, right? You kinda read it out in English. It's almost like it's COBOL. It's so readable here. So I'm gonna use code actions and I'm gonna implement this. So there we go. We have function area takes in a reference to self and produces a float64.

Since it's for a rect, that means self has all the properties of the rectangle. So if I go self., you can see height, width, x, y. So I'm gonna go like this return width times self.height. There we go. We nailed it. All right, first try. So I highly recommend executing a little YAP, I call it YAP.

Yank that paragraph and then you can just paste it. Wait, if you're not using Vim you can't do that. I use Vim by the way. All right, so now we need to implement it for circle. So, implement area for circle. All right, so now it's gonna complain well hey wait a second.

Area or circle doesn't have width or height well let's change that so we gotta go radius times self.radius because remember pi r squared times pi, right? Now this is an interesting one, ellipses. Hey now, this is kind of an interesting one you have to import pi, pi doesn't exist, but look at what you can import.

You can import it for a float 32 or a float 64. Yeah, no. Yeah, so make sure you implement it for or import it for a float 64 because if you don't well, you can't multiply a float 32 by a float 64. They're different types. Remember that, there we go.

So now we've implemented area for both circle and rectangle. So let's go down into our main function and let's create a rectangle. Let rect=Rect and go x is 0.0, y is 0.0, width is 10.0, height is 10.0, and don't forget your semicolon. All right, so let's do the same thing but let's do it for circle.

So I'm gonna create a circ=Circle and replace this last one with a radius. Trust me, this is gonna get so exciting, okay? I want you to follow along because this is so exciting. All right, here we go. So we're gonna do a little println! And let's do this, and go circ.area.

All right, it worked out. Let's do a rect.area. Look at that, we called area. Pretty cool, right? Very basic trait stuff. Nothing fancy here, I don't think anyone is impressed, right? See, that's not that was like a Yao Ming face right there.
>> There's a bunch of claps.

>> A lot of claps, I know, very excited. Not cool at all. I do agree it's actually not all that cool. There we go, if I run it, look at what I get. Fantastic, that makes about, that's approximately correct. Radius 10, 10 times 100 times 3.14, boom, we got that correct.

3.14 versus 100, fantastic, we have done it. Thank you for all the claps, many appreciations. All right, so now, you're not impressed and I do not blame you. It's time to be more impressive, all right? So let's use this area trait interface, but let's make a very small change.

Let's move our rect and circle definition to a new file called So let's go in here. Do you see that actually do :w in the terminal happens all the time, victim of using Vim, suffering from success. All right, so let's create a file called And then let's go back to our main file and just take out these two items right here and let's move it to our file.

So however you want to do that you can do that we need to make a small change to the structures to make it worked out for us. Let me show you the small change. Just write the word pub everywhere, everything let's make everything public. Look at that. Okay, I just made everything public.

We then make it all public. Now you'll notice at the very top of the file it says file not included in module three. This is just an error that happens because we haven't told Rust we wanna use this file. So let's go back to our main file and tell it we wanna use this file.

This is part of our definition so when you build the program please build this also. So I'm gonna jump back to that main file and I'm gonna go like this, mod shapes. There we go. I just said hey, make sure you use that. But look at what's happening right here.

We have this weird error going on. Cannot find rect in the scope. Well, this makes sense, right? If you've ever used JavaScript, you know you have to like import the thing in. Exact same concept. I'm just gonna use, whoopsies, some of those sweet auto, those code actions. Import it in, look at that.

Now it says use shape rect. So right, this one says include it in the build. This one says we're gonna use this one. So use shapes rect, there we go, we'll do the same thing down here on circle. Import that one in, I'm gonna hit Save and look at that, everything is fine we're building.

>> This is just like the beginning. It's just like the takeoff ramp.

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