In this lecture, we're going to learn about generics.
They are a feature, a frequently used in angular.
They allow functions or classes to be strict and flexible at the same time.
Generics function similarly to parameters, but with data types.
Sounds confusing.
Let's look at an example and the motivations behind generics.
They're super simple.
Once you see them in action for this demonstration, let's work inside an empty file.
We will create a new file called generics dots.
Inside this file, we will create a class called Q.
In this scenario, let's pretend this class can handle a collection of items.
It'll manage from moving and pushing items into the class that's already possible with array functions.
However, you may want to replicate this behavior if you're interested in having refined control over
how items get added or removed from an array.
For this example, we will restrict the data type that can be added or removed from the array.
First, we will create a property called data.
It'll be a private property.
Privatising their way will prevent external code from interacting with the era, we are being very strict
with our array.
Next, we will define a method called add.
This method will accept an argument called item.
This argument will be pushed into the data era with the push function.
Lastly, we will create a method called Remove.
The remove method will remove the first item in the array inside this method, we will call the shift
function on the data array.
The current implementation has a couple of problems.
The biggest problem is how we're adding and removing values at the moment.
Any value can be added or removed.
Let's look at an example below this class, we will create a new instance of the class called name Q.
Our queue will hold an array of names.
Let's try pushing two names by calling the ad function.
The first name will be a string.
The second name will be a number.
We're pushing in two different data types, which we may not want.
We're not restricting the type of data that can be pushed into the object.
One solution would be to add annotations to the parameters of the function.
Let's try that in the ad functions parameters.
We will set the type two string.
By adding this annotation, TypeScript will throw an error.
It's not letting us push a number, which is great.
It helped us catch an error.
Let's change this value to a string.
So far, so good, right?
Let's try creating a new queue.
The new queue will be called no queue.
Unlike the first queue, this queue will store numbers.
Let's try adding a new number with the add function.
We'll get an air, even though we have a different queue.
We can't use another type.
Our queue is restricted to storing strings.
We may want to restrict our array to a single data type.
But the data type should be flexible from queue to queue.
How do we get the best of both worlds?
One solution would be to duplicate the Class one version for strings, another four numbers.
Unfortunately, that's not scalable.
If we want our class to be reusable, developers should be able to use it without modifying the original
class.
We can tackle this issue by using generics.
A generic is a placeholder for data types.
After the class name, we'll add a pair of angle brackets inside these brackets.
We will give the placeholder a name.
We will use the letter T.
Next, we will update the ad function by setting the parameters data type two T.
Afterward, we will annotate the data property to be an array of the tea type.
Lastly, we will add angle brackets to both new instances.
They must be placed before the parentheses.
The first instance will have string.
The second instance will have a number.
Let me break down what's going on.
The generic is the letter T in the angle brackets.
It's a placeholder for the data type.
The letter T can represent any data type.
This can be strings, numbers, Boolean or custom types by defining this generic.
We can use it anywhere in our class.
In this case, we're adding it to the item parameter in the add function.
If this generic is set to string, the item parameter will be restricted to strings.
If it represents the number type, the item parameter will be restricted to numbers, so on and so forth.
We can configure the data type when we create a new instance, which we're doing in the code below.
For example, the first instance is setting the type two string.
Therefore, only strings can be pushed into the array.
We can prove this by removing the quotes from one of the values in the add function.
An air gets thrown by the compiler.
It's telling us the type must be string.
Despite these string data Typekit not being present in the class TypeScript can intelligently restrict
the values to strings and the second instance.
The array is restricted to numbers by using generics.
We can have type safety while allowing our class to be flexible for any type.
You may be wondering why the letter T..
Truthfully, we can use any name we'd like.
For example, we can swap this name with the word baseball.
This class will still work.
However, it's common practice to use the letter T, which is short for a type.
It's not required, but standard among developers.
In most documentation and examples, you will find developers like to use the letter T at the end of
the day.
It's up to you to decide if you want to follow this naming convention.
Generics can be applied to functions and class methods.
They're not exclusive to classes.
The first example shows how the generic can be used for our parameters and return type.
The same goes for the class method throughout this course.
Generics will pop up.
It's not common to create them, but it's always good to know how they work under the hood.
In a similar sense, decorators are another feature will be using, but won't be writing.
It is still good to know how they work, though we'll learn about decorators in the next lecture.