Generic code to increase reusability

Generic is available in almost all typed language. It allows transforming your code in a reusable fashion without having to rely on unsafe casting to retrieve the value stored in an object. Without generic, there are different ways to achieve reusability. For example, you can have an interface with an any type.

That would make the field open to receive any kind of object, hence being reusable for many scenarios:

interface ReusableInterface1 {
entity: any;
}

A slightly better way would be to specify whether we want to accept primitives or only objects:

interface ReusableInterface2 {
entity: object;
}

const ri2a: ReusableInterface2 = { entity: 1 }; // Does not compile
const ri2b: ReusableInterface2 = { entity: { test: "" } };

In both cases, the problem comes when we want to use the reusable field. The same result occurs with any or object, which is that we do not have access to the original variable's member because we do not have a way to know what was the original type:

const value = ri2b.entity; // value -> "object"

In this code, it is impossible to use .test of the entity without casting back to the entity. In that particular type, it is an anonymous type but still possible:

const valueCasted = value as { test: string };
console.log(valueCasted.test);

However, generic can remove this hinder to access the original type by bringing the type of the object into the definition of the type without tampering the type to be isolated with a single type. To create a generic function, interface, or class, you need to use the smaller or bigger sign, < >:

interface MyCustomTypeA {
test: string;
}

interface MyCustomTypeB {
anything: boolean;
}

interface ReusableInterface3<T> {
entity: T;
}

The name between the brackets does not matter. In the following code, we are using the entity with two custom interfaces and use them as type T. We are also using a number directly. We can use all the possible types because we do not have a generic constraint, yet, in place:

const ri3a: ReusableInterface3<MyCustomTypeA> = { entity: { test: "yes" } };
const ri3b: ReusableInterface3<MyCustomTypeB> = { entity: { anything: true } };
const ri3c: ReusableInterface3<number> = { entity: 1 };

The biggest advantage is that if we access the object, the field entity is of a T type, which changes depending on how the object was created:

console.log(ri3a.entity.test); // "yes" -> string
console.log(ri3b.entity.anything); // true -> boolean
console.log(ri3c.entity); // 1 -> number
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.188.201