TypeScript - 联合类型
TypeScript - 联合类型
Section titled “TypeScript - 联合类型”联合类型允许你定义一个变量或函数参数,它可以持有多种特定类型的值。它们提供了灵活性,同时仍然保持一定程度的类型安全,因为值必须是联合类型列表中指定的类型之一。
通过在两个或多个类型注解之间使用管道符号 (|) 来创建联合类型。
let variableName: Type1 | Type2 | Type3 | ...;示例:联合类型变量
Section titled “示例:联合类型变量”let identifier: string | number;
identifier = 12345; // 正确console.log(`Numeric identifier: ${identifier}`);
identifier = "user-abc-123"; // 正确console.log(`String identifier: ${identifier}`);
// identifier = true; // 错误:类型 'boolean' 不能赋值给类型 'string | number'。在此示例中,identifier 可以存储 string 或 number 类型的值。
使用联合类型
Section titled “使用联合类型”当你拥有一个联合类型的值时,TypeScript 只会允许你访问那些该联合类型中所有类型共有的成员(属性或方法),而不会首先执行类型检查。
function printValue(value: string | number) { // console.log(value.toUpperCase()); // 错误:类型 'string | number' 上不存在属性 'toUpperCase'。类型 'number' 上不存在属性 'toUpperCase'。 // console.log(value.toFixed(2)); // 错误:类型 'string | number' 上不存在属性 'toFixed'。类型 'string' 上不存在属性 'string'。
// toString() 在 string 和 number 类型中都是共有的(通过原型链),所以这是允许的: console.log(value.toString());}使用类型守卫窄化联合类型
Section titled “使用类型守卫窄化联合类型”为了处理特定类型独有的成员,你需要在一个特定的代码块中将联合类型窄化 (narrow) 为一个更具体的类型。这可以通过使用类型守卫 (Type Guards) 来实现。
常见的类型守卫包括:
typeof检查: 用于原始类型,如string、number、boolean、symbol、bigint、undefined、function。instanceof检查: 用于检查对象是否是特定类的实例。- 属性存在性检查 (
in运算符): 检查对象是否包含某个特定属性。 - 等值检查: 与特定的字面量值或
null/undefined进行比较。 - 自定义类型守卫函数: 返回类型谓词 (
parameterName is Type) 的函数。
示例:带有类型守卫的联合类型和函数参数
Section titled “示例:带有类型守卫的联合类型和函数参数”function processInput(input: string | string[] | null) { if (typeof input === 'string') { // 在这里,TypeScript 知道 'input' 是一个 string 类型 console.log(`Processing string: ${input.toUpperCase()}`); } // 使用 Array.isArray 进行数组检查(比 typeof 返回 'object' 更好) else if (Array.isArray(input)) { // 在这里,TypeScript 知道 'input' 是一个 string[] 类型 console.log(`Processing array: Found ${input.length} items.`); input.forEach((item, index) => console.log(` Item ${index}: ${item}`)); } // 显式检查是否为 null else if (input === null) { console.log("Input is null."); } // 注意:如果 null 是唯一剩余的选项,则这里不需要 else}
processInput("hello");console.log("---");processInput(["Apple", "Banana", "Cherry"]);console.log("---");processInput(null);数组和对象的联合类型
Section titled “数组和对象的联合类型”联合类型可以应用于数组元素或对象属性。
示例:联合类型数组
Section titled “示例:联合类型数组”要允许数组包含来自联合类型的不同类型的元素,可以使用括号:
// 可以存储 string 或 number 类型的数组let mixedArray: (string | number)[] = [1, "two", 3, "four"];
mixedArray.push(5);mixedArray.push("six");// mixedArray.push(true); // 错误:类型 'boolean' 的参数不能赋值给类型 'string | number' 的参数。
console.log("Mixed Array:", mixedArray);
// 使用类型守卫处理混合数组mixedArray.forEach(item => { if (typeof item === 'string') { console.log(`String item: ${item.toUpperCase()}`); } else { console.log(`Number item: ${item.toFixed(1)}`); }});示例:用于数组类型的联合类型
Section titled “示例:用于数组类型的联合类型”这定义了一个变量,它可以存储一个数字数组 (array of numbers) 或一个字符串数组 (array of strings),但不能在同一个数组中混合这两种类型。
let list: number[] | string[];
list = [1, 2, 3, 4]; // 正确 - 数字数组console.log("Numeric Array:", list);
list = ["a", "b", "c"]; // 正确 - 字符串数组console.log("String Array:", list);
// list = [1, "a"]; // 错误:类型 '(string | number)[]' 不能赋值给类型 'number[] | string[]'。 // 类型 '(string | number)[]' 不能赋值给类型 'string[]'。联合类型是一个强大的特性,用于建模一个值可以合法地属于多种类型之一的场景,它在增强代码灵活性的同时,通过类型守卫指导开发者正确处理每一种可能性。