در حال بارگذاری ...

Arrow vs Function Syntax2:30

parentheses here for the parameters and then we return our function body. So this is using the arrow syntax for JavaScript or TypeScript which is my preferred syntax you'll see me use that throughout this entire series but I'll just show you you can use it with a more traditional function syntax if you're more comfortable with that. So we can do function addTwoNumbers which takes a which is a number and b which is a number and then returns a number but this is just going to be a more traditional function syntax like that so we can also use that syntax if you prefer however I don't really like this old syntax I much prefer the arrow syntax so you'll see me use that from now on. So we've seen some pretty trivial examples so far we've seen some strings and numbers and a basic function that takes two numbers and returns a number but a more realistic example might be say a function that fetches a User from the database so we might have

Typing Object Returns3:20

strings and numbers and a basic function that takes two numbers and returns a number but a more realistic example might be say a function that fetches a User from the database so we might have a function called getUserById which might take an id which is a string and that might return an object like in reality this would be a database lookup but we're just going to give the id straight back and let's just say we get a name back of Michael. Now how do we add a type definition for the return type here so in the most basic sense we're getting an object back the object has an id which is a string because it's exactly what we pass in and we're also getting a name which is a string so that's how we would type this in its most basic form we're just getting an object back so we just use an object syntax we define the properties and the types of those properties and then we have type safety here so if we were to consume this well first of all let's just comment

so we just use an object syntax we define the properties and the types of those properties and then we have type safety here so if we were to consume this well first of all let's just comment this out and we'll get an error immediately we'll get an error saying property name is missing in type { id: string } and where TypeScript is getting that type { id: string } from is it's inferring it from this return type so it knows this function always returns this and this only has a property of id so this is what this first type here is in this error message but it's required in type { id: string; name: string } which is what we've declared the return type to be for this function so we've said this function should return this TypeScript can infer that it's only returning the id and that's how we read that error message right there so we uncomment out the name we get everything as we would expect now we could also consume this so we could say let's say this is somewhere else

Consuming Return Types4:54

id and that's how we read that error message right there so we uncomment out the name we get everything as we would expect now we could also consume this so we could say let's say this is somewhere else in the code equals getUserById whoops let's getUserById and we've said it's a string because it's a uuid or something so let's just do that so now we have a User we don't have to actually declare a type on this user because this function has a declared return type of this object TypeScript knows that a User has to be of that type so if we do something like user.email or if we spelled that right but it won't matter if we do user.email we're going to get a TypeScript error saying email does not exist on type id and name which is the declared return type on this function but we could do user.name and TypeScript is perfectly happy with that and it even tells us that name is going to be a string so TypeScript is is pretty intelligent and it can do good type

but we could do user.name and TypeScript is perfectly happy with that and it even tells us that name is going to be a string so TypeScript is pretty intelligent and it can do good type inference which is really handy. Now the problem with defining the type of a User like this inline as an object and explicitly listing out all the keys and property types is that if we have large objects this is just going to get very very verbose and hard to reason about and read. It also means that if we want to, let's say we want another function that takes a User, so let's say we have a saveUser function which takes a User and then saves it. For now, we'll just console.log it out saving User and then we'll log out the User. So let's say we had a saveUser and we wanted to add type safety to this, it would be a little bit annoying to have to like copy and paste this and then paste that there and then if you want to add another filter or User.

Reusable Types with Interfaces6:40

and we wanted to add type safety to this it would be a little bit annoying to have to like copy and paste this and then paste that there and then if you want to add another filter or User you have to go find everywhere in the codebase that you need to update so in order to handle that TypeScript gives you a couple of ways to define types for reuse in your codebase and the most common way is via an interface interfaces in TypeScript basically define the shape of a data we'll go over interfaces in a lot more detail in a later lesson so do not worry and they're basically defined like this so use the interface keyword you give the interface a name in this case User and then you specify the properties so we have an id of string and a name which is a string and use semicolons not commas to end the line of the declaration so let's say we also want an age which is a number and say an email address which is a string so let's say our User now has this

semicolons not commas to end the line of the declaration so let's say we also want an age which is a number and say an email address which is a string so let's say our User now has this shape so now instead of using this literal object type we can just type it as a User here and one benefit of using interfaces instead of inline objects is if we have a look at this error message we see here type id and name is missing the following properties from type User age and email so you see here now we actually get a named type in our error message of User and that's because we've defined an interface of User so this allows TypeScript to give us much much more specific error messages if i were to just copy and paste this inline uh for to replace this User like we had before and i were to hover over this um you see my error message is now less helpful it just says uh the missing the following properties from type and it enumerates out the object type there

Structural Typing Pitfalls10:38

and the name of this id is just going to return straight back again and the book name can just be TypeScript is best script and then let's also do a get const book equals getBookById and let's also give it a save save method so saving book this is going to take a book this is going to be of type book and this is going to be called saveBook so here we have two interfaces defined one is a User and one is a Book they both have the exact same properties id and name and they both have the exact same types of those properties which are string so what that means in a language like TypeScript is that books and users are completely interchangeable and they satisfy the same contract and that means they can be used interchangeably to highlight this i'm going to call saveUser and saveBook but i'm going to pass saveUser a book and just show that it doesn't error so let's call

and that means they can be used interchangeably to highlight this i'm going to call saveUser and saveBook but i'm going to pass saveUser a Book and just show that it doesn't error so let's call saveUser but pass it the book and let's call saveBook and also pass it the book so you would expect saveUser to error because we're passing in a Book but that's not going to be the case so let's run this and see what happens we've called saveUser uh saving User and it's book and it's clearly the book and saving Book is clearly the book as well and again we can put a User in here we're not going to get a TypeScript error at all because this perfectly satisfies the contract they're structurally the same so they get treated the same now there's one little additional bit of complexity on top of this if i go to my Book definition and i give this another property of releaseDate which is a Date um then getBookById also needs to return a releaseDate which can

complexity on top of this if i go to my book definition and i give this another property of releaseDate which is a date um then getBookById also needs to return a releaseDate which can just be a new Date() so now our saveBook can no longer take a User because our releaseDate is missing in type User but required in type Book so again this nice helpful TypeScript error message just goes straight to the end releaseDate is missing on User but required in Book and that's because we have a User here so if we update this to Book the error goes away now you might have noticed that saveUser isn't throwing an error message even though it's getting a Book and these contracts are no longer the same the User does not have a releaseDate but the Book does so what is going on here now the reason this is an error is because where we're consuming a User we're only using a subset of the data that is on Book so if we have a look at Book Book contains id and name

we've used this saveUser and saveBook example possibly not the most informative so this is obviously a TypeScript file i can't just write jsx or html in here but imagine we had a save method instead of doing this let's do like propOne and it's going to be the userId and let's do propTwo and it's going to be the userName let's also do this for book except this is obviously now going to be the book and then this also has a third property which is going to be book.releaseDate so now we can see like this saveBook even though we're only console.loging out we're accessing this releaseDate property which means if we pass the user in here this is just going to be null so this is might actually be a bad idea but let's do toISOString there we go so now we're actually performing something on this so if we pass the user into here classic JavaScript error cannot a property

Optional Properties and Safety15:33

might actually be a bad idea but let's do toISOString there we go so now we're actually performing something on this so if we pass the user into here classic javascript error cannot get property toISOString does not exist on type undefined because releaseDate is not defined on a User so this is probably a more informative example so what do you think would happen though if i made releaseDate an optional property so stop and think about this for a sec pause this video and try and guess and we'll go through together and explain what happens and why so to make something optional in TypeScript we add this questionMark syntax so that's just saying releaseDate is an optional property it may or may not exist so that means we can delete it off this getBookById again this would be a database lookup so it may or may not have it on here so let's pretend this record doesn't have it also need to make this because releaseDate is optional we're going to

again this would be a database lookup so it may or may not have it on here so let's pretend this record doesn't have it also need to make this because releaseDate is optional we're going to have to make this an optional chaining for the two toISOString and then now here we can see saveBook doesn't throw an error because this is an optional property we're doing a check for it so let's run this and just check that it works cool saving book it's taken a user and propThree is just undefined so yeah we can see that by making it optional we have to handle optional in the code flow which means we can pass it a user and nothing's going to break but as soon as we make this not optional again we're going to get our error here our releaseDate it's going to be a new Date and we're going to get this error here again so yeah that's that's what i mean by it can't it can't error if they share the same contract or a superset of the contract so

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟