&
) and union (|
) operators. These operators allow developers to create complex types by combining simpler ones. In this blog post, we’ll explore the fundamental concepts, usage methods, common practices, and best practices related to the &
and |
operators in TypeScript.&
)The intersection type operator (&
) combines multiple types into one. A variable of an intersection type must satisfy all the types in the intersection. In other words, it has all the properties and methods of each individual type.
type Admin = {
role: 'admin';
manageUsers: () => void;
};
type Employee = {
employeeId: number;
work: () => void;
};
type AdminEmployee = Admin & Employee;
const adminEmployee: AdminEmployee = {
role: 'admin',
employeeId: 123,
manageUsers: () => console.log('Managing users...'),
work: () => console.log('Working...')
};
|
)The union type operator (|
) allows a variable to have one of several types. A variable of a union type can be of any of the types in the union.
type StringOrNumber = string | number;
const value1: StringOrNumber = 'hello';
const value2: StringOrNumber = 123;
Intersection types are useful when you want to combine the features of multiple types. For example, you can use them to create a type that has the properties of two or more existing types.
type Person = {
name: string;
age: number;
};
type ContactInfo = {
email: string;
phone: string;
};
type PersonWithContactInfo = Person & ContactInfo;
const person: PersonWithContactInfo = {
name: 'John Doe',
age: 30,
email: '[email protected]',
phone: '123-456-7890'
};
Union types are handy when a variable can have different types depending on the situation. For instance, a function parameter might accept either a string or a number.
function printValue(value: string | number) {
if (typeof value === 'string') {
console.log(`The string value is: ${value}`);
} else {
console.log(`The number value is: ${value}`);
}
}
printValue('hello');
printValue(123);
Intersection types can be used to implement mixins, which are a way to combine multiple classes into one.
class Logger {
log(message: string) {
console.log(`[LOG] ${message}`);
}
}
class Validator {
validate(value: any) {
return typeof value === 'string';
}
}
type LoggerValidator = Logger & Validator;
const loggerValidator: LoggerValidator = {
...new Logger(),
...new Validator()
};
loggerValidator.log('Validating value...');
const isValid = loggerValidator.validate('hello');
console.log(`Is valid: ${isValid}`);
Union types are often used for optional parameters in functions. You can use them to specify that a parameter can either have a certain type or be undefined
.
function greet(name: string | undefined) {
if (name) {
console.log(`Hello, ${name}!`);
} else {
console.log('Hello!');
}
}
greet('John');
greet(undefined);
While intersection and union types can be powerful, it’s important to avoid creating overly complex types. Complex types can make your code hard to understand and maintain. If a type becomes too complicated, consider breaking it down into smaller, more manageable types.
When working with union types, it’s often necessary to use type guards to determine the actual type of a variable. Type guards are expressions that perform a runtime check that guarantees the type in a certain scope.
function printLength(value: string | number[]) {
if (typeof value === 'string') {
console.log(`The length of the string is: ${value.length}`);
} else {
console.log(`The length of the array is: ${value.length}`);
}
}
printLength('hello');
printLength([1, 2, 3]);
The &
and |
operators in TypeScript are powerful tools for working with types. Intersection types allow you to combine multiple types into one, while union types allow a variable to have one of several types. By understanding the fundamental concepts, usage methods, common practices, and best practices related to these operators, you can write more robust and flexible TypeScript code.