We have two regular interfaces and a generic interface. Generics make great containers because they can contain anything. We can have a container of crocodiles and a container of taxes. Maybe we need a red crocodile container and a blue crocodile container.
If we want to be more specific about what we want to contain, we can use a generic constraint. The constraint changes the generic from accepting anything to accepting anything with these types.
When we set the values, the IDE gives us auto complete and tells us the types for the values. We're getting auto complete for the property name and the value type. Again, auto complete for the property name and the value type. One more time, auto complete for the property name and the value type.
You have to pass the type argument with an interface constraint, but if you forget, the IDE will let you know. Class generic constraints work a little differently. First, let's make a class with one property that is set after instantiation. Notice that we're not setting the constraint type. When we set the class E croc unit properties, we get the type information from the constraint.
As long as the property only has the constraint type, the compiler is cool with it. If we add a property that's not in the constraint, the IDE will let us know. If we do pass the type argument, we get the type information from the constraint and the type argument.
Let's make another class that uses the constructor's shorthand for setting the value on instantiation. If we don't pass a type argument, we can add extra properties as long as the class instance has the constraint type. no complaints from the compiler.
If we want to be more specific, we can still pass a type argument. Now that we have passed a type argument, we're getting the same level of type information from the IDE. The IDE and the compiler will let us know that likes Cheetos doesn't exist on a blue croc.
To review, generic types can contain anything, but a generic constraint can contain anything that has the constraint type. For class generic constraints, if we don't use the constructor shorthand for setting properties on instantiation, we can get away without passing the type argument but the property can only contain the constraint type.
When we pass the type argument, our property will have that value too.
If we do use the constructor shorthand for setting properties on instantiation and we want more specificity, we can pass the type argument. If we want less specificity, we don't have to. As long as the instance has the constraint, we can add extra properties.