Exploring Advanced Type Features in TypeScript
Understanding the Power of TypeScript's Advanced Type Features
Table of contents
TypeScript is a superset of JavaScript that provides optional static type checking and type annotations. One of the main benefits of using TypeScript is that it allows you to catch errors early during development before they make it to production.
In addition to basic types like string
, number
, and boolean
, TypeScript also supports advanced type features that allow for creating more complex and powerful types. In this article, we'll take a closer look at some of these advanced type features and how they can be used in TypeScript.
Mapped Types
Mapped types allow for transforming the properties of an existing type into a new type. Mapped types are defined using the keyof
operator, which returns the type of the keys of an object or interface. Mapped types are useful for creating new types that are similar to existing types but with some modifications.
Here's an example of a mapped type that makes all properties of an interface optional:
interface Person {
name: string;
age: number;
address: string;
}
type OptionalPerson = {
[K in keyof Person]?: Person[K];
};
// Usage:
const optionalPerson: OptionalPerson = { name: 'John' };
In the example above, we define an interface Person
with three required properties. We then define a mapped type OptionalPerson
that transforms each property into an optional property using the ?
operator. This allows us to create a new type OptionalPerson
that is similar to the Person
interface but with optional properties.
Conditional Types
Conditional types allow for creating types that depend on a condition. Conditional types are defined using the extends
keyword, which checks if a type extends another type. Conditional types are useful for creating types that have different behaviour depending on a condition.
Here's an example of a conditional type that returns a number
if the input type is a number
, or a string
otherwise:
type MyConditionalType<T> = T extends number ? number : string;
// Usage:
const myNumber: MyConditionalType<42> = 42;
const myString: MyConditionalType<'hello'> = 'hello';
In the example above, we define a conditional type MyConditionalType
checks if the type T
extends number
. If the condition is true, the type is set to number
, otherwise, it is set to string
. This allows us to create a new type MyConditionalType
has different behaviour depending on the input type.
Intersection Types
Intersection types allow for combining multiple types into a single type. Intersection types are defined using the &
operator, which combines the properties of two types. Intersection types are useful for creating types that have properties from multiple sources.
Here's an example of an intersection type that combines two interfaces:
interface Person {
name: string;
age: number;
}
interface Employee {
company: string;
salary: number;
}
type PersonAndEmployee = Person & Employee;
// Usage:
const personAndEmployee: PersonAndEmployee = {
name: 'John',
age: 30,
company: 'Acme Inc',
salary: 50000,
};
In the example above, we define two interfaces Person
and Employee
, and then define an intersection type PersonAndEmployee
combines both interfaces using the &
operator. This allows us to create a new type PersonAndEmployee
that has properties from both Person
and Employee
.
Conclusion
These are just a few examples of the advanced type features available in TypeScript. By using these features