TypeScript Type 类型别名详解
目录
概述
type 关键字用于创建类型别名,可以为任何类型定义一个新名字,包括原始类型、联合类型、交叉类型、元组等。
为什么使用 type?
- 提高代码可读性
- 减少重复代码
- 更灵活的类型定义
- 支持复杂的类型操作
基本用法
1. 基本类型别名
// 简单类型别名
type UserID = string;
type Age = number;
type IsActive = boolean;
// 使用类型别名
let userId: UserID = "u123";
let userAge: Age = 25;
let active: IsActive = true;
2. 对象类型
// 对象类型别名
type User = {
id: string;
name: string;
age: number;
email?: string; // 可选属性
};
// 使用对象类型
const user: User = {
id: "1",
name: "John",
age: 30
};
3. 联合类型
// 联合类型
type Status = "pending" | "approved" | "rejected";
type ID = string | number;
// 使用联合类型
let status: Status = "pending"; // 只能是这三个值之一
let id: ID = "123"; // 可以是字符串或数字
高级用法
1. 泛型类型别名
// 泛型类型别名
type Container<T> = {
value: T;
tag: string;
};
// 使用泛型类型
const numberContainer: Container<number> = {
value: 123,
tag: "number"
};
const stringContainer: Container<string> = {
value: "hello",
tag: "string"
};
2. 交叉类型
type Person = {
name: string;
age: number;
};
type Employee = {
company: string;
role: string;
};
// 交叉类型
type EmployeeInfo = Person & Employee;
// 使用交叉类型
const employee: EmployeeInfo = {
name: "John",
age: 30,
company: "Tech Corp",
role: "Developer"
};
3. 条件类型
// 条件类型
type IsString<T> = T extends string ? true : false;
type IsNumber<T> = T extends number ? true : false;
// 使用条件类型
type Result1 = IsString<"hello">; // true
type Result2 = IsString<123>; // false
4. 映射类型
// 映射类型
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Optional<T> = {
[P in keyof T]?: T[P];
};
// 使用映射类型
type ReadonlyUser = Readonly<User>;
type OptionalUser = Optional<User>;
与 Interface 的区别
1. 语法差异
// Interface
interface Animal {
name: string;
age: number;
}
// Type
type Animal = {
name: string;
age: number;
};
2. 扩展方式
// Interface 扩展
interface Animal {
name: string;
}
interface Dog extends Animal {
breed: string;
}
// Type 扩展
type Animal = {
name: string;
}
type Dog = Animal & {
breed: string;
};
3. 合并声明
// Interface 可以合并声明
interface User {
name: string;
}
interface User {
age: number;
}
// 结果:User 有 name 和 age 属性
// Type 不能合并声明
type User = {
name: string;
}
type User = { // 错误:重复的标识符
age: number;
}
最佳实践
1. 命名约定
// 使用描述性名称
type HttpResponse<T> = {
data: T;
status: number;
message: string;
};
// 使用后缀表示类型种类
type UserProps = {
// ...props for user component
};
type UserState = {
// ...state for user component
};
2. 组合类型
// 基础类型
type BaseEntity = {
id: string;
createdAt: Date;
updatedAt: Date;
};
// 组合��用
type User = BaseEntity & {
name: string;
email: string;
};
type Product = BaseEntity & {
title: string;
price: number;
};
3. 类型保护
type Success<T> = {
type: 'success';
data: T;
};
type Error = {
type: 'error';
error: string;
};
type Result<T> = Success<T> | Error;
function handleResult(result: Result<User>) {
if (result.type === 'success') {
console.log(result.data.name); // 类型安全
} else {
console.log(result.error); // 类型安全
}
}
实际应用场景
1. React 组件类型
type Props = {
title: string;
children: React.ReactNode;
onClick?: () => void;
};
const Button: React.FC<Props> = ({ title, children, onClick }) => {
return (
<button onClick={onClick}>
{title}
{children}
</button>
);
};
2. API 响应类型
type ApiResponse<T> = {
data: T;
metadata: {
page: number;
total: number;
};
};
type User = {
id: string;
name: string;
};
async function fetchUsers(): Promise<ApiResponse<User[]>> {
const response = await fetch('/api/users');
return response.json();
}
3. 状态管理
type State = {
user: User | null;
isLoading: boolean;
error: string | null;
};
type Action =
| { type: 'LOGIN_REQUEST' }
| { type: 'LOGIN_SUCCESS'; payload: User }
| { type: 'LOGIN_FAILURE'; payload: string };
function reducer(state: State, action: Action): State {
switch (action.type) {
case 'LOGIN_REQUEST':
return { ...state, isLoading: true };
case 'LOGIN_SUCCESS':
return { ...state, isLoading: false, user: action.payload };
case 'LOGIN_FAILURE':
return { ...state, isLoading: false, error: action.payload };
}
}
总结
-
type 的优点:
- 可以为任何类型创建别名
- 支持复杂的类型操作
- 更好的类型推断
- 更灵活的类型定义
-
使用场景:
- 联合类型和交叉类型
- 工具类型
- 条件类型
- 复杂的类型定义
-
最佳实践:
- 使用描述性名称
- 合理组合类型
- 保持类型简单清晰
- 适当使用泛型