Using Extract, Generic T extends to control designated properties of Unioned classes (typescript)

ref – https://stackoverflow.com/questions/56067863/discriminating-a-union-of-classes

We declare abstract class Fruit, which says any class that extends this MUST declare readonly property fruitType of type string.

So we create Banana, which extends Fruity. We must declare property readonly fruitType and initialize it with string banana
We also give it unique properties length and color.

We do this same for Pear and Apple, and give them their own unique characteristics. But they all must have property readonly fruitType of type string.

Then, we create a Union of class types called KnownFruits. KnownFruits is a Union of class Banana, Pear, and Apple. Basically we’re grouping them together. KnownFruits is the group fruits I want to select from later.

So we know that KnownFruits type restricts the type that it can reference into the group that consists of Banana, Pear, and Apple.

Now let’s get a union of its keys. We basically get the group of keys by giving the property name ‘fruitType’ to the group (Union) of class types like so:

Extracting the wanted class by using key string

we declare a type called FruitDiscriminator

This type consists of generic T where it extends from FruitTypes. When generic T extends from FruitTypes this means, it means
whatever object T you pass in must be ‘apple’ OR ‘banana’ OR ‘pear’.

So when we pass in this object, it must contain a property called fruitType that is of type union FruitTypes.
In other words, T extends FruitTypes means we restrict generic class to MUST BE FruitTypes, which is “banana” | “pear” | “apple”
So if we put in ‘pineapple’ for fruitType, it will get error.

Now, the functionality or class we want to use is called Extract.

We Extract the class we want from the union of our classes (KnownFruits), by using property fruitType. As mentioned above, property fruitType must be of type FruitTypes.
Extract simply takes the fruitType (say ‘apple’), and then extract the class type from union KnownFruits. In our case of ‘apple’, it will extract Apple.

Assignment example

So let’s try it out with a basic example.

Type ‘”pineapple”‘ does not satisfy the constraint ‘”banana” | “pear” | “apple”‘.(2344)

So let’s use a string that satisfies union FruitTypes.

Great it worked, but we see another error here. Type ‘{}’ is missing the following properties from type ‘Banana’: fruitType, length, color(2739)
So because ‘banana’ will return us the class type Banana, we must fill in the missing properties length and color.

So now, the error goes away. Notice also that FruitDiscriminator’s generic type T forces fruitType to have the same string of ‘banana’.

Function example

Now we create a function called createFruit. It takes in two parameters. The firstone is fruitType, which is of type generic T, that extends from FruitTypes. Ok so it is union “banana” | “pear” | “apple”.
Then we have props, which is FruitDiscriminator of the same generic T.

or using generics: