Unsurprisingly, Typescript is a superset that came to bring Object Oriented concepts to the Javascript language. However, some keywords of this language created by Microsoft still generate doubts.
In addition to modeling entities and objects of value through classes, it is also possible to perform such modeling using an interface or a type. Below are an example of modeling using each language feature.
class People {
name: string;
age: number;
}
interface People {
name: string;
age: number;
}
type People = {
name: string;
age: number;
}
At this point you might be thinking: "If it's possible to model in any of the three ways, why should I use or understand 'type'?". The answer is simple, there are uses that only the use of the type resource allows, below I talk more about each of these scenarios.
Type aliases
As the name implies, it is possible to nickname, that is, to give a new name to an already existing type, whether it is declared as a class, interface, another type, or a primitive type.
type Student = People;
type Guid = string;
In the example above, we created a type called "Student" which is basically an alias for the "Person" model. We also created a type for a unique identifier, mapped over the string type, as we don't have a Guid type (as C# does) in Typescript.
Aliasing an existing type, especially primitive types, is useful for bringing semantics in line with the context in which that type will be used. A string-type identifier does not provide clues about the format or value of the ID, unlike a GUID type, which already has its format in the name.
Template literals
This is the ideal feature for aliasing one or more static values that are enumerable. Did not understand? Let's go for an example.
type MonthNumber = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
Above are the indices for each month of the year. The advantage of using literal types is to be warned when an incorrect value, that is, one that does not belong to the defined set, is used, as shown in the example below:
Union types
In short, it is possible to declare a type that accepts multiple other types (primitives, class, interface, type, literal), that is, a type that unites other types.
Below we create an ID type that accepts both string values (if it is a GUID, for example) and number type (if it is an auto-incremental integer, for example).
type ID = string | number;
const peopleId: ID = 13;
const postId: ID = '08288a85-b79b-4022-a0dd-1563bd0f5de1';
Intersection types
In addition to allowing multiple types to be accepted as valid for a new one, it is also possible to merge several types, that is, to create a type that is the fusion of properties of two or more others. This usage scenario is restricted to declaration of entities, does not apply to primitive values.
In the example below we create an entity (Person) and a value object (Address). With the "&" operator we were able to unify the two types into a new one, an entity to represent a person with an address. This third type will contain all the attributes of the two that originated it.
class People {
name: string;
age: number;
id: ID;
}
interface Address {
country: string;
city: string;
}
type PeopleWithAddress = People & Address;
const george: PeopleWithAddress = {
age: 19,
city: 'Serra',
country: 'BR',
id: 25,
name: 'George',
zipCode: 251475899
};
Final considerations
With these features there are no more excuses to leave values like strings or numbers scattered around the code, or to repeat all the properties of one model in another. It is possible to have development time validation of values and save template declaration lines :)
Fontes:
Types aliases
Literal types
Union types
Intersection types
Top comments (0)