TypeScript is a natural extension of JavaScript that’s used in many projects in place of JavaScript.
However, not everyone knows how it actually works.
In this article, we’ll look at how to work with objects in TypeScript by creating intersection types and checking object structures.
Checking Properties
This means that we can’t use the typeof
operator to check the type of objects.
Instead, we must find better alternatives.
One way is to check if a property is in the object.
For instance, we can use the in
operator:
arr.forEach(a => {
if ("breed" in a) {
console.log("animal");
} else {
console.log("person");
}
});
The in
operator checks if the 'breed'
property is in an object.
It checks both its own and inherited properties.
And it returns true
if a property is found in any of those places and false
otherwise.
However, this doesn’t help us if a property is in both types.
Type Predicate Function
We can also check if a property is undefined
to check if an object is of a certain type.
For instance, we can write:
arr.forEach(a => {
if (typeof a.breed !== "undefined") {
console.log("animal");
} else {
console.log("person");
}
});
This is similar to in
except that we used typeof
to check for a property instead of using the in
operator.
Type Intersections
We can use type intersections to define 2 object types that are combined together.
A variable assigned to an object type should have all the properties from both types rather than some of them like union types.
For instance, we can create an intersection type and assign it to a value by writing:
type Thing = { name: string };
type Animal = { breed: string };
const animal: Thing & Animal = {
name: "james",
breed: "dog"
};
We defined a Thing
type and an Animal
and combined them into an intersection type by using the &
operator.
This means that animal
must have properties from both Thing
and Animal
included.
If we skip one or more of them, then the TypeScript compiler will give us an error.
For instance, if we have:
const animal: Thing & Animal = {
name: "jame"
};
Then we’ll get ‘Type ‘{ name: string; }’ is not assignable to type ‘Thing & Animal’. Property ‘breed’ is missing in type ‘{ name: string; }’
We can use intersection types for introducing new properties to existing objects.
For instance, if we have:
type Thing = { name: string };
type Animal = { breed: string };
const thing: Thing = {
name: "james"
};
const animal: Animal = {
breed: "cat"
};
const cat: Thing & Animal = {
...thing,
...animal
};
Then TypeScript compiler won’t throw an error because it recognizes that name
and breed
are part of the Thing & Animal
type.
As long as the property names and the corresponding data type match, the TypeScript compiler can figure out that it matches the structure of an intersection type.
Merging Properties with the Same Type
We can also merge types with overlapping properties.
For instance, if we have:
type Thing = { name: string };
type Animal = { name: string };
Then anything assigned to the Thing & Animal
type variable would have the string property called name
.
Merging Properties with Different Types
If there are properties with different types, then both properties will be merged together as an intersection.
For instance, if we have:
type Thing = { age: string };
type Animal = { age: number };
const thing: Thing = {
age: "1"
};
const animal: Animal = {
age: 1
};
const cat: Thing & Animal = {
...thing,
...animal
};
Then we would get an error from the compiler since age
has type string & number
which no value matches.
Therefore, we shouldn’t have properties with different types in the object types that we intersect.
Conclusion
We can create intersection types to merge object types into one type.
Then when a variable or parameter has the intersection type, it must include all the properties of both types, and the data type of the property must be an intersection of data types from both types.
We can check the property type with the in
operator or typeof
to check the structure of each object to determine their type.