Video details

TypeScript Berlin Meetup #7 - Mughees Ilyas - Understanding Alias types and tuples 101

TypeScript
09.04.2021
English

â—­ In this talk we will go over the Alias types and how are they different from interfaces, what are tuples and what we can do with them. We will also cover how alias in tuples can be used.
------------------------ đź“š Resources:
âś… Subscribe to Prisma: https://www.youtube.com/channel/UCptAHlN1gdwD89tFM3ENb6w?sub_confirmation=1 âś… Get help from the Prisma Community: https://slack.prisma.io/ âś…
Learn more about Prisma: â—­ Website: https://www.prisma.io â—­ Docs: https://www.prisma.io/docs â—­ Quickstart: https://pris.ly/qstart
------------------------ đź’¬ Connect with Prisma: Twitter: https://twitter.com/prisma Instagram: https://www.instagram.com/prisma.io/ TikTok: https://www.tiktok.com/@prismadata Facebook: https://www.facebook.com/prisma.io LinkedIn: https://www.linkedin.com/company/prisma-io
------------------------ Prisma sponsors human-reviewed, professional closed captions for ANY video valuable to our community (for example, about: Node.js, TypeScript & Type Safety,
Prisma, databases, etc). Get your FREE captions here: https://pris.ly/closedcaptions

Transcript

Hello. So my name is Louis. I'm a frontend developer and I work at Ultimate Ultimate. We do automation for the customer support chat, and if you have ever talked to a customer support agent on a website and think that it's very good, very awesome. Probably support it's our bot. And today we'll be talking about alias and tapes and how alias compares to interfaces. Most of the type ship community in the initial stages are usually when you're building a project, you will see interfaces a lot and then the type is came in and this is how you define them. They are small differences between the interfaces and types, and we will go through them. But let's go through the user journey, how the user comes into these types and how we separate them. So usually when a user start writing something, it will start writing a function. It will put up parameter in it. The function will grow bigger and bigger. The parameters will start getting bigger and bigger, and then you will see. Okay, we need to take them out. You take them out and you create types here. I just have an employee which have a type of string or number ID type and the employer type can be interned permanent employee and permission employee. And then here I just combine all these types into one and make a whole type to pass it to our function. There are two fold benefit for that. If you have your function parameters like this. The problem is that even if you have often parameters like your probation period is a question Mark, there was supposed to be another one. Think here like sheer then provision period. But if you have them in line in your function, if you want to pass the last parameter, even though the other two are optional, you will have to pass them anyway, because the functions cannot skip the parameter. If you have to pass the last one by taking it out and making it an object. Now you only pass things that you want and then skip the optional ones. You can potentially do the same thing with interfaces. You define an interface, ID and employee type, and then you can define an employ and extend. But the main thing is that for interfaces they have to be type named, so you cannot define a primitive type of interface. It always has to be an object with a name near it. And that is where our type list comes in handy. So just a side by side comparison. If we are doing it for the type and interfaces with interfaces, you have animals. You want to extend it to something you extended with types. We have again animal, if you want to add, just use an in person thing and then both of them have the same thing in the end. So what you can't do with type and do with interfaces. So if you have a type name and then you define it again, the type ship will start throwing errors that you cannot do that. You can only have one type for one name if you do the same thing with the interfaces, what type strip do is that it just combines both interfaces and make one interface out of it. So if you have an interface name and interface name with these three properties, in the end, you will get interface which will have name, first name and last name. Why is it bad or is it good? It depends on what type of projects you are doing, but mainly if you have global types or global interfaces, I would prefer types because then if you try to define something which is already defined by some other user, you can either extend it or look into it at. Okay, fine. I need some other type with interfaces. There's just a mixed box that you define interface globally in one place. Same name came in another place, and then you just have a lot of properties that you think where it comes from. This is the same thing that you have two types. You want to combine them, you can combine them and and find. You can actually combine two types in an interface as well. But then you don't. You cannot pass anything inside it. I mean, if you're just combining them same with the interfaces. So if you want to combine two interfaces, you can create a type out of it, so they are more or less interchangeable at this point. Now we are going to go through things that are that you cannot do with interfaces, but you can do with types. The first thing is the or operator or the Union operator. So if you have to type, you can use this or operator to tell that my animal will either be a fish or a bird. And this is the sort of functionality that the interface don't have right now. Also, you can if you want to do a Union type of interface, again, you will have to do it using a type alias type. So in the end, I see more benefit of using type aliases than interfaces. And again, like I said in the start that the type aliases have primitive types that you can define in any number of ways. So I can say my name is string in my ID number. Just that. And you probably want to do something like a type in for where it can be either a string or an object. And interfaces usually cannot perform these sort of operations. It just really struggles with that. And this is my favorite part of the the computed properties. So let's take an example that you want to type on objects which will have first name, surname, address, maybe age or like XYZ elements in it, and all of them will be Typed as string. So rather than typing them one property at a time, you can use this in property with the key and it just takes all of the keys and assign a single type to it. How is that useful? Sometimes it just gets cumbersome to right break properties when you know that all of them will be of save at the same time. So you just define the keys and then use the computer properties to expand your type fully. Also, not only can it compute the properties from the keys, it can actually take another type and then extend it and create a new type out of it all together, it can perform some operations in it. Like I defined my type as person and it is name and string. So what I'm doing here right now? I'm saying that all the keys in my Mark them optional. So because I'm creating a new type out of my old one, I'm marking all of them as often and then attaching my address string to it. So potentially it becomes what's in the last one. So all of these operations become name age question Mark and then address becomes the compulsory one. Why would you want to do that? So, for example, you have a type which you use normally and all of these properties are required, but then came in API which has a similar properties, but most of them are not required. And then you create rather than creating the new type for all of these properties, you just use these computed property address in your type and just create a new type altogether from it. And it helped me really in creating these extended type for APIs that I'm using from some SIV source, which I'm not sure of. Okay, this ends the alias versus interfaces. Anyone have any questions so far like why we use one or the other? I would say that generally I am in opinion that we should be using type is more in our project and interfaces should only be used if we are exposing our library to some external source. So we use interface there somebody wants to use our library. They have the similar name in their interfaces in their project. It will not complain. It will just merge. It will all go smoothly. And it wasn't a lot. I think there's only one thing that you can do with you can have. However. So one thing that I think you still can do with Typ Alesis is when you want to extend or define the signature of a class, you can have the types constructor done through them. So you need still an interface with the constructor. Yeah, hosted inside. This is a big difference. Yeah, that is one of the big difference. If you want to extend your interface, but with types, you can still use the implement functionality and implement a classroom from it, so you cannot extend it crew, but you can sell implements through it, but generally that this is one of the differences as well, that if it's a static type, and you know that you're not going to use classes for it. You're not going to have a function in them or you're not going to have a constructor property in them. Then it makes more sense to use type aliases than interfaces. There was another question. Okay. Yes. Something that interfaces can do. No, I think anything that interface can do can be done through type aliases type hosting. So at least it was a feature in the previous version of type scripts. I don't know if it's still relevant in version four plus, but once it was defined at the type, so I cured. It is the same difference between bar let and cost. So bar get hosted hoisted to the top of the time were less and change the scope, but also our supposed to be the capture the declaration point and are not going to be posted at the top of the file. Therefore you could not resent them before them being declared. And the same thing was for the type palaces. So files is used to be not hoisted were interfaces were always that I think is not true anymore because yeah. Yes. Very bad at throwing. So there is in fact one dimension in which interfaces are better than type ads, which is editor support. If you have over type in vs. Code and that is a type alias, then vs. Code will try to show you your documentation. It will try to resolve the type all the way to the bottom, and that will admittedly, make some of these types very hard to read because it will remove any kind of abstraction that you had there or something, and it will make all of your types look way more complex than they are. If you use interfaces for that matter, vs. Code will immediately stop at that interface level. It will show you what interface it is, what properties exist, but it won't go deeper and resolve these properties. So if you have types that you expect to be inspecting a lot in your editor, there's this one argument to use interfaces, that's one. And then there's this other very contrived argument, which is if you have let's say, a million interfaces that each extend each other, then through some magic computer science type system thing, types are way less fast to compile them interfaces. But that is if you have like a million interfaces. So please please don't accepted arguments. Yes. One other thing that interfaces can do is if there is an error, it really will tell you the exact property in the error that is wrong in the interface. But in types it will tell you the generic types, which is more present. I tend to agree with that point, but overall, it's generally my opinion that when we are using internally in our project and we know that we are not going to extend our types or there is no constructor, they are just defining what the object looks like, then the type ILLIUS provide more functionality in terms of Union and intersection and compute properties. Okay, so then we move on to something which is a little bit controversial because people have asked me what's the use case for it. So tuples. Yes, that is what that was my answer, but. Okay, so we want to define an array which is of type, string and number, and we are really, really, really worried about what is on the zero index. What is on the first index? In some world where we are worried about that, we cannot define our array using the first method, which is the popular method of defining an array, which is string a number. We use a second method which ensures that our first element will always be a string, and our second element will always be a number. There are a couple of use cases for that. One would be when we are typing our arguments for the function where we want to make sure that everything comes in in order. And second might be that some API needs some special array with different types. It gives a lot of functionality. So if we define so it's a very big scene, almost lost the cursor. So if we want to define the string and a number, we can define it like that. If we try to define with a third element, it will give an error on the length. But because it's JavaScript and TypeScript tends to stop you from doing things that should not be done. And JavaScript allows you to do things that are you know, we can do work anyway. So we can still push the element into the array and it will not complain. But the element we are pushing still has to conform to the type that are of tuple. So if you push 56, it will say it's fine. But if we try to push an element which is a boolean, it will still complain that the argument type is not compatible with it. And yeah, we cannot change the order. The order has to remain same. And the other thing when I was saying that it can be used in defining the functional parameters, it is mainly due to the fact that we can name our tuples, and this is a sort of functionality that we don't usually have when we are defining an array through conventional means. So if you know that you have four arguments which are going to your function, you can define a tuple which will have their name named element attached to it. These are just aliases, and they don't really matter because you still access the array using the index and you can distract it as you want. What is the caveat here is that if you're putting the named apples, each of the element has to be named. You cannot just name one and lead the rest. All the arguments either has to be either named or not named. What it can do is that it can use the spread operator to define some really cool type of things. So if I define something like at least two numbers which has number number and then a spread operator. So what I do is that it will define an array which will have at least two elements or X number of numbers. So if I try to pass one element, it will start to throw error. And the other cool thing is that it can have spread operator in the middle of it. So you have your left hand or your right hand which have type, and then in the middle you can have anything. And the spread operator is by default an optional parameter. So if you're defining a spread operator, it becomes optional. Either you pass them or not. It doesn't really make a difference. So here when we have a string, a spread operator of number array and boolean, we can define something like Hello 2345 true, or we can say Hello true. In either case it works. It will not throw error. The other thing that with the spread operator is that you cannot have two spread operators, because then that's how TypeScript will get confused. Like we are the one spread operators ends and the other starts. You can actually do these couple things in interfaces as well is something like this. So what you do is that you try to extend your arrange and then you say that. Okay. It will have a number and a boolean types, and then you define the index in it with a number and boolean and its length. And then you can use it same as your tuples. But then obviously it's a matter of choice. That why do all of this certainly can do the simple as. But one thing that is really cool about the interface is that you can use some genetic types and really get into the basic details of how we are doing the tuples. So here what I am doing is that my interface will have a generic type of Tu and and which will return an array of type T U. So I just have to pass what type and what length it has to be, and it will automatically create type out of it. And then we can use it as a tape. It is just to show that we have the Apple type, but when we didn't have it, the similar functionality could have been achieved using interfaces at some level. Question yes. Do you want to execute? I'm good. I wonder how the type it looks like. Only the first two arguments are Typed and the rest are not. Is it correct? Sorry. I mean, the first two indexes of the array zero and one. So when you're defining your array through an interface like that, it means that your T and the number of indexes that you want to define and rest of the indexes will have to follow what we have already defined. So there will be any or will be last type. So there will be a number and boolean only. But I mean second and third will be either so or uh, exactly. So that is at the end where I'm saying extend a T and U. That means that it can only return the type T and U. Yeah. The inference between the first example I sent in before. This is just the normal way of doing things. And this is a generic function I've created out of it. Meaning that I was just lost the extent that I at the beginning. If you just define an interface with the signature of having, like, an index number of the type and the length when you use the ability of having all the methods which are attached to. Yes, you always have all the functionality. That is exactly why here, even though I've defined it as a string and a number, I was able to sell push it because in the end, it's still an array and you can do all sorts of oppression on it. Okay. So is that also a way how for example, if you use a library like axles and you can create basically a function that returns an array where the first value is null and the second is the response or the first value is the arrow, and the second value is null. Yes. So that is more or less. You can achieve that functionality using the tapes. Now, mostly it has been defined using the interfaces. I have not included a very large example because there was one where there is a function in which tries to combine two arrays, and then the function does not know what type of arrays are. And then you just have to overload like, ten different methods to make it timeship compliance. And with something like this, it can be done in two lines with tuples. Nice. Thanks. Thank you. So can you define types with genetics? Yes. Because you define this fixed length area as an interface. Yes. Can you do the same type type with type? You don't have to because you're already when you're creating a tuple, it already length pound. So when you say that. But if you want to reuse this interface, this type with different types. So this type should support generics. Can you do this with type aliases and tuples? It can. So what you can do is that rather than saying number number, you can say T, U or T whatever you want to define, and then you can pass the types later on and it will be lens bound. Listen. Okay, then. Thank you.