So we got started with generics and hopefully it's clear what types does here.
We passed some extra information into the merge function so that we can work in a better way with the
result of the merge function and that's typically what generics are therefore they allow you to continue
working with your data in a typescript optimal way.
Now in this case here however we would have a problem if I pass in let's say just a number 30 year of
course typescript now frozen Arrow because it tried to access to h but accessing the name would work
nonetheless if we save that it compiles without errors and if I print the overall merge object we see
what I get back is just a hobby is a name in my object which makes sense because 30 is a number.
And when we pass that as a second argument to object a sign which we in the end are doing here.
Well then this just fails silently javascript doesn't throw an error it doesn't complain but of course
it all doesn't merge 30 into the newly created object.
You see there is no 30 in this object.
Now how which javascript do so because 30 is not an object an object a sign only is capable of merging
different objects with each other.
So what we in the end want to say well we don't care about the exact type.
We don't care about the exact structure of the object you're providing here for a new entity.
But what we do care about is that both parameters both types t and you should be any kind of object
but they should be an object at all times.
And currently we're not saying that currently we're just saying this should be of any type I don't care.
Now often that's not OK.
You want to restrict the types of T and you hear some of your generic types and you can do that with
type constraints for generic types.
You can set certain constraints regarding the types your generic types can be based on and you do this
with the extents keyword here in the angled brackets after the type which you want to constrain.
So here we could say extends Object and with that I'm saying the T type can be any object with any structure
but it has to be an object we can do the same for you.
And if I do that you see now I already get an error here in the ITC and if I try to save that I also
get an error in the compiler because the type 30 argument here is not a signal to type object.
So that's of course the behavior we want here.
Now we're forced to pass in an object again which is like this now we're forced to pass this in again
and therefore we improve does function because now it really works and we no object assign ones to objects.
So in the end we want to guarantee that we get two objects here by setting certain constraints on our
generic types and these constraints here can be anything you can refer to object to string you could
use your own type if you had it.
You can also use union types here if you want to you're really flexible there.
You can set any constraints you want.
And of course you don't have to constrain all generic types if you just want to constrain you.
You can do that in this example it just makes sense to constrain both because object design once two
objects here but you're really flexible there.
It is important to be aware of that concept of constraints though because that allows you to work with
generic types and a better in an optimal way which is why it's unnecessary errors or strange behaviors
as we had it before.