TypeScript Types - Advanced Type Features
TypeScript has powerful type features that make your code more flexible and type-safe. Let's explore advanced types!
Union Types
A value can be one of several types:
let value: string | number;
value = "hello"; // OK
value = 42; // OK
value = true; // Error!Union Types in Functions
function printId(id: string | number) {
if (typeof id === "string") {
console.log(id.toUpperCase());
} else {
console.log(id.toFixed(2));
}
}Intersection Types
Combine multiple types:
interface Person {
name: string;
}
interface Employee {
employeeId: number;
}
type Staff = Person & Employee;
const staff: Staff = {
name: "John",
employeeId: 123
};Literal Types
Specific values as types:
type Direction = "up" | "down" | "left" | "right";
function move(direction: Direction) {
// direction can only be one of the four values
}
move("up"); // OK
move("north"); // Error!Generics
Create reusable, type-safe code:
function identity<T>(arg: T): T {
return arg;
}
let output1 = identity<string>("hello");
let output2 = identity<number>(42);Generic Interfaces
interface Container<T> {
value: T;
getValue(): T;
}
const stringContainer: Container<string> = {
value: "hello",
getValue: () => "hello"
};Generic Functions
function getFirst<T>(items: T[]): T | undefined {
return items[0];
}
const firstNumber = getFirst<number>([1, 2, 3]); // number | undefined
const firstString = getFirst<string>(["a", "b"]); // string | undefinedConditional Types
Types that depend on conditions:
type IsArray<T> = T extends any[] ? true : false;
type Test1 = IsArray<string[]>; // true
type Test2 = IsArray<string>; // falseMapped Types
Create new types from existing ones:
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
interface User {
name: string;
age: number;
}
type ReadonlyUser = Readonly<User>;
// { readonly name: string; readonly age: number; }Utility Types
TypeScript provides built-in utility types:
Partial
Make all properties optional:
interface User {
name: string;
age: number;
}
type PartialUser = Partial<User>;
// { name?: string; age?: number; }Required
Make all properties required:
interface User {
name?: string;
age?: number;
}
type RequiredUser = Required<User>;
// { name: string; age: number; }Pick
Select specific properties:
interface User {
name: string;
age: number;
email: string;
}
type UserName = Pick<User, "name" | "email">;
// { name: string; email: string; }Omit
Remove specific properties:
interface User {
name: string;
age: number;
email: string;
}
type UserWithoutEmail = Omit<User, "email">;
// { name: string; age: number; }Type Guards
Narrow types with type guards:
function isString(value: unknown): value is string {
return typeof value === "string";
}
function process(value: string | number) {
if (isString(value)) {
// TypeScript knows value is string here
console.log(value.toUpperCase());
} else {
// TypeScript knows value is number here
console.log(value.toFixed(2));
}
}Visual Explanation: Type System
Here's how TypeScript types work:
Type Definition:
┌─────────────────────────────┐
│ type MyType = string | number│
│ │
│ Value can be: │
│ - string │
│ - number │
│ - NOT boolean │
└─────────────────────────────┘
│
│ TypeScript checks
│
┌────┴────┐
│ │
Valid? Invalid?
│ │
▼ ▼
Compiles Error!Frequently Asked Questions (FAQ)
Q1: What's the difference between union and intersection?
A:
- Union (|) - Value can be one type OR another
- Intersection (&) - Value must be ALL types
Q2: When should I use generics?
A: When you want to create reusable code that works with different types:
function getFirst<T>(items: T[]): T {
return items[0];
}Q3: What are utility types?
A: Built-in TypeScript types that transform other types:
Partial<T> // Make all optional
Required<T> // Make all required
Pick<T, K> // Select properties
Omit<T, K> // Remove propertiesQ4: What's a type guard?
A: A function that narrows a type:
function isString(x: unknown): x is string {
return typeof x === "string";
}Q5: Can I create my own utility types?
A: Yes! Use type aliases:
type Nullable<T> = T | null;
type Optional<T> = T | undefined;Q6: What's the difference between type and interface?
A:
- type - Can use unions, intersections, more flexible
- interface - Can be extended, merged, better for objects
Q7: What are conditional types?
A: Types that depend on conditions:
type IsString<T> = T extends string ? true : false;Q8: What's mapped types?
A: Creating new types by transforming properties:
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};Q9: Can I use generics with classes?
A: Yes!
class Container<T> {
value: T;
constructor(value: T) {
this.value = value;
}
}Q10: How do I learn advanced types?
A: Start with basics (unions, generics), then learn utility types, then conditional and mapped types. Practice with real projects!
Next Steps
Now that you understand advanced types, here's what to learn next:
- Next: Learn about TypeScript with React - Use advanced types in React
- Explore TypeScript Best Practices - Write better TypeScript
- Understand TypeScript Compiler Options - Configure TypeScript
- Master TypeScript Patterns - Common type patterns
Advanced types make TypeScript powerful. Practice using them to write better code!