在鸿蒙 ArkTS(基于 TypeScript 的扩展)中,Union 类型 和Type Aliases(类型别名) 是类型系统的两大核心特性。它们虽然常被同时使用,但解决的问题截然不同。本文将通过完整示例深入剖析二者的区别与应用场景。
一、Union 类型:灵活的多类型容器
核心概念 :允许变量持有多种类型中的任意一种 ,使用 |
符号组合类型。
关键特性:
- 运行时需类型保护(
typeof
/instanceof
) - 增强 API 灵活性
- 完美处理可选值(如
T | null
)
完整示例:
typescript
// 1. 基础类型联合
type Primitive = string | number | boolean;
const logValue = (value: Primitive) => {
if (typeof value === "string") {
console.log(value.toUpperCase());
} else {
console.log(value.toFixed(2)); // 自动推断为 number | boolean
}
};
// 2. 对象类型联合
class Cat {
meow() { console.log("Meow!") }
}
class Dog {
bark() { console.log("Woof!") }
}
type Pet = Cat | Dog;
const handlePet = (pet: Pet) => {
if (pet instanceof Cat) {
pet.meow(); // 类型保护
} else {
pet.bark(); // 自动推断为 Dog
}
};
// 3. 带字面量的联合
type Status = "loading" | "success" | "error";
const setStatus = (status: Status) => {
console.log(`Current status: ${status}`);
};
典型应用场景:
- 函数参数支持多类型:
parseInput(input: string | number)
- 状态机表示:
type State = "idle" | "running" | "paused"
- 网络响应处理:
type Response = SuccessData | ErrorInfo
二、Type Aliases:类型系统的快捷方式
核心概念 :为现有类型创建可复用的别名 ,使用 type
关键字定义。
关键特性:
- 简化复杂类型声明
- 提升代码可读性
- 实现 DRY(Don't Repeat Yourself)原则
完整示例:
typescript
// 1. 简化复杂结构
type UserProfile = {
id: string;
name: string;
preferences: {
theme: "light" | "dark";
notifications: boolean;
};
};
const updateProfile = (profile: UserProfile) => {
/* 实现细节 */
};
// 2. 函数类型签名
type FetchHandler = (
url: string,
options: { timeout: number; retries: number }
) => Promise<Response>;
const fetchData: FetchHandler = async (url, opts) => {
/* 实现细节 */
};
// 3. 元组类型简化
type Point3D = [number, number, number];
const calculateDistance = (p1: Point3D, p2: Point3D) => {
/* 三维空间计算 */
};
// 4. 泛型别名
type ApiResponse<T> = {
data: T;
timestamp: Date;
statusCode: number;
};
const userResponse: ApiResponse<UserProfile> = await fetchUser();
典型应用场景:
- 统一项目类型规范:
type UserID = string
- 简化复杂对象结构
- 自文档化代码(见名知意)
- 泛型类型模板
三、黄金组合:Union 与 Alias 的协作
二者结合使用能最大化类型系统的优势:
typescript
// 1. 联合类型别名化
type Identifier = string | number | { id: string };
// 2. 复杂联合结构
type NetworkState =
| { status: "idle" }
| { status: "loading"; progress: number }
| { status: "success"; data: ApiResponse<any> }
| { status: "error"; code: number };
// 3. 类型安全的Redux模式
type Action =
| { type: "ADD_TODO"; text: string }
| { type: "TOGGLE_TODO"; id: number }
| { type: "DELETE_TODO"; id: number };
const reducer = (state: Todo[], action: Action) => {
switch (action.type) {
case "ADD_TODO":
// action.text 可用
return [...state, { text: action.text }];
case "TOGGLE_TODO":
// action.id 可用
return state.map(todo =>
todo.id === action.id ? { ...todo, done: !todo.done } : todo
);
// 无需 default case(类型穷尽检查)
}
};
四、核心差异总结
| 特性 | Union 类型 | Type Aliases |
|-----------|--------------|------------------|------------|
| 本质 | 类型组合(逻辑或) | 类型重命名 |
| 主要目的 | 扩展变量允许的类型范围 | 简化复杂类型声明 |
| 运行时影响 | 需要类型保护机制 | 纯编译时概念 |
| 典型符号 | ` | `(管道符) | type
关键字 |
| 最佳实践 | 处理不确定类型的场景 | 创建领域特定语言(DSL) |
| 嵌套能力 | 可包含其他联合类型 | 可封装任意类型(包括联合) |
五、何时使用哪种类型?
选择 Union 类型当:
- 需要处理多种可能的输入类型
- 构建状态机或复杂工作流
- 变量可能为不同类型(如
string | null
)
选择 Type Alias 当:
- 重复使用复杂类型结构
- 提升代码可读性(如
type Coordinate = [number, number]
) - 统一项目类型规范
- 创建自解释的API签名
组合使用场景:
-
为联合类型创建有意义的别名:
type CardType = "visa" | "mastercard" | "amex"
-
简化包含联合的复杂结构:
typescripttype PaymentMethod = { type: CardType; last4: string; expiry: Date; }
六、高级技巧:类型操作
typescript
// 1. 联合类型提取
type StringOrNumber = string | number;
type ExtractString<T> = T extends string ? T : never;
type Result = ExtractString<StringOrNumber>; // = string
// 2. 条件类型分发
type ToArray<T> = T extends any ? T[] : never;
type NumOrStrArray = ToArray<number | string>; // = number[] | string[]
// 3. 模板字面量类型(ArkTS 4.0+)
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
type ApiEndpoint = `/api/${string}`;
type FullRoute = `${HttpMethod} ${ApiEndpoint}`;
总结
- Union 类型 是类型系统的 "或运算符",扩展值的可能性
- Type Aliases 是类型系统的 "命名工具",提升代码表达能力
- 二者结合 能构建精确灵活的领域模型
在鸿蒙应用开发中:
typescript
// 典型ArkTS组件属性模式
type ButtonProps = {
text: string;
size: "small" | "medium" | "large";
onPress: () => void;
style?: StyleProp; // 联合类型 + 可选
};
@Entry
@Component
struct MyButton {
@Prop config: ButtonProps; // 类型别名复用
build() {
Button(this.config.text)
.onClick(() => this.config.onPress?.())
}
}
掌握这两种类型特性,将使你的鸿蒙应用获得更强的类型安全保障和更优雅的代码架构。