TypeScript高级类型
TypeScript提供了多种高级类型帮助我们在定义变量和函数时更精确和灵活地描述数据类型
联合类型(Union Types)
联合类型使用|允许一个变量的类型是多个类型之一
JS
let value: number | string;
value = 42; // OK正确
value = "hello"; // OK正确
value = true; // 错误,不能是 boolean 类型
👉联合类型通常与null或undefined一起使用
JS
const sayHello = (name: string | undefined) => {};
👉联合类型使用函数
JS
function printId(id: string | number) {
console.log(`ID: ${id}`);
}
printId("abc123"); // OK, 可以是字符串
printId(12345); // OK, 也可以是数字
联合类型与类型保护
👉使用typeof进行类型保护
JS
function print(value: string | number) {
if (typeof value === "string") {
console.log("String: " + value);
} else {
console.log("Number: " + value);
}
}
print("Hello"); // String: Hello
print(123); // Number: 123
👉使用in保护类型
js
interface Car {
drive(): void;
}
interface Boat {
sail(): void;
}
type Vehicle = Car | Boat;
function operate(vehicle: Vehicle) {
if ("drive" in vehicle) {
vehicle.drive(); // 确保 vehicle 是 Car 类型
} else {
vehicle.sail(); // 确保 vehicle 是 Boat 类型
}
}
联合类型与数组
👉数组的元素也可以是多个不同类型的值
JS
let array: (string | number)[];
array = ["hello", 42, "world", 100]; // OK
array = [true, "foo", 10]; // 错误, 因为 true 不是 string 或 number
JS
// 数组
let arr=[];
let narr:(String|number)[];
narr=['age',14];
console.log(narr,'narr');
联合类型与null和undefined
JS
let value: string | null | undefined;
value = "Hello"; // OK, 是字符串
value = null; // OK, 是 null
value = undefined; // OK, 是 undefined
联合类型与接口
使用多个接口时,可以通过联合类型让变量兼容多种类型的接口
JS
interface Dog {
bark(): void;
}
interface Cat {
meow(): void;
}
type Pet = Dog | Cat;
function makeSound(pet: Pet) {
if ("bark" in pet) {
pet.bark(); // 如果是 Dog 类型
} else {
pet.meow(); // 如果是 Cat 类型
}
}
联合类型与any
JS
let value: string | any;
value = "Hello";// OK, 是字符串
value = 123;// OK, 是数字
value = { name: "John" }; // OK, 是对象
value = true;// OK, 因为 any 允许任何类型
联合类型与枚举
JS
enum Status {
Active = "active",
Inactive = "inactive"
}
let status: Status | string;
status = Status.Active; // OK
status = "active"; // OK
status = "busy"; // OK
可辨识联合(Discriminated Union)
联合类型结合字面量类型和类型守卫,就是可辨识联合类型,也称为(discriminated union)
在可辨识联合中,联合类型的每个成员都有一个共同的属性
这个属性的值在每个成员中是唯一的(通常是字面量类型的值)
通过这个属性,TS可以准确地推断出当前值的类型进行类型保护。
核心:使用一个字面量类型的属性作为“标志”来区分不同类型的成员,通常我们称为**“辨识属性”**(Discriminant Property)
JS
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; size: number }
| { kind: "rectangle"; width: number; height: number };
function area(shape: Shape): number {
if (shape.kind === "circle") {
return Math.PI * shape.radius * shape.radius;
} else if (shape.kind === "square") {
return shape.size * shape.size;
} else {
return shape.width * shape.height;
}
}
const circle: Shape = { kind: "circle", radius: 10 };
console.log(area(circle)); // Output: 314.1592653589793
👌 使用可辨识联合可以避免手动的类型检查
JS
type Animal =
| { type: "dog"; bark: boolean }
| { type: "cat"; meow: boolean }
| { type: "bird"; fly: boolean };
function makeSound(animal: Animal): void {
if (animal.type === "dog") {
console.log("Woof! Is it barking?", animal.bark);
} else if (animal.type === "cat") {
console.log("Meow! Does it meow?", animal.meow);
} else {
console.log("Chirp! Can it fly?", animal.fly);
}
}
const dog: Animal = { type: "dog", bark: true };
makeSound(dog); // Output: Woof! Is it barking? true
👌 用于类型保护
JS
function getDescription(animal: Animal): string {
switch (animal.type) {
case "dog":
return `This dog can bark: ${animal.bark}`;
case "cat":
return `This cat can meow: ${animal.meow}`;
case "bird":
return `This bird can fly: ${animal.fly}`;
default:
return "Unknown animal";
}
}
交叉类型 (Intersection Types)
使用 & 来组合多个类型,表示同时满足多个类型的条件
JS
type Person = { name: string; age: number };
type Contact = { phone: string; email: string };
let personContact: Person & Contact = {
name: 'John',
age: 30,
phone: '123456789',
email: 'john@example.com',
};
JS
type Person = { name: string };
type Worker = { job: string };
type Employee = Person & Worker;
let employee: Employee = { name: "Alice", job: "Engineer" };
js
type personName={name:string};
type personAge={age:number};
type Person= personAge&personName;
const personinfo:Person={
name:'张三',
age:14,
};
console.log('personinfo',personinfo);
类型别名(Type Aliases)
使用 type为类型定义一个别名,可以为复杂的类型(任何类型例如:联合类型、交叉类型、字面量类型等)创建简短的别名
JS
type StringOrNumber = string | number;
let a: StringOrNumber = 'Hello'; // 正确
let b: StringOrNumber = 123; // 正确
JS
type StringOrNumber = string | number;
let value: StringOrNumber = "hello";
value = 42;