If you already have a subscription, you can sign in.
Enjoy free content straight from your inbox 💌
00:00
Here we have a simple draft step class that implements a first in first out collection, which is also known as a queue. It provides two methods push to push items into the queue and pop to pop items out of the queue in a first, in, first out manner. Now, this is a general purpose queue and it supports items of any type. So we can push in a number and we can push in a string. However, because it supports items of any type, when we pop out items from the queue, we do not get any guarantee about what the type of that item will be at compile time.
00:32
So developer's assumption of what a popped out item might be. For example, in the second call, based on the two precision call, it seems that the developer is expecting a number. However, since the type of the items in the queue was not constrained, we were allowed to push in a string and this particular call will result in a runtime error. Now, in a language that does not support generics, we can overcome this issue by using class specialization. So what we do is that we extend the Base Q class with a class specially designed for a particular item type
01:06
where we annotate the push and the pop items with that item type. And within the method bodies, we simply call the super class methods, which support all data types. Now, when we expect to be working with numbers, instead of using the Base Q class, we create instances of this number queue, and this highlights errors when we try to push in something that is not a number, and therefore when we pop an item, we can be guaranteed that it will be of type number. Now creating these class specializations specifically for the purpose of data type annotation can
01:38
quickly become cumbersome. For example, if we needed a queue of strings at this point, we would have to duplicate this code only to change the annotations from number to string. Fortunately, TypeScript does support generics, and so we don't need to create these specialization classes. So let's get rid of this number Q class and go back to our original example. We can add a generic type parameter as an argument to the Q class, and then we can use this type to annotate a push and pop functions. Now, when we create instances of the Q class,
02:12
we can pass in the generic type argument. For example, if you want a queue of numbers, we pass in the type number because we've annotated the push method to only accept items of type T. When we are passing in the generic argument number, this shows that the instance will only accept items of type number for the push call. So we get an error when we try to push a string and we can easily fix it. And now our two precision call will work because we are only pushing numbers. So to summarize, generics allow you to add type arguments that can be used to enforce a relationship
02:45
between different members of a piece of code. Here we are using a generic argument in the Q class and storing it in type T. We use this to ensure that only items of type T are accepted by the push method and subsequently returned from the pop method.