TS 入门(四):TypeScript 高级类型与类型操作

前言

在前三章中,我们介绍了 TypeScript 的基础知识、函数与对象类型。在本章中,我们将探讨更高级的类型和类型操作,包括联合类型、交叉类型、字面量类型、类型断言、类型兼容性和类型守卫等内容。通过这些高级特性,你将能够编写出更加灵活和强大的代码。

回顾

在上一章中,我们学习了以下内容:

  • 函数类型:包括基本函数类型、可选参数和默认参数、剩余参数。
  • 对象类型:包括基本对象类型、可选属性和只读属性。
  • 类型别名和接口:包括类型别名、接口扩展。
  • 类型推断和上下文类型。

在这里插入图片描述

正文开始如果觉得文章对您有帮助,请帮我三连+订阅,谢谢💖💖💖


1. 联合类型和交叉类型

a. 联合类型

联合类型(Union Types)表示一个值可以是几种类型之一。使用竖线(|)分隔多个类型。

let id: number | string;
id = 101;
id = "ABC123";

function printId(id: number | string) {
  if (typeof id === "number") {
    console.log(`ID number: ${id}`);
  } else {
    console.log(`ID string: ${id}`);
  }
}

b. 交叉类型

交叉类型(Intersection Types)表示同时包含多个类型的特性。使用和号(&)合并多个类型。

interface Person {
  name: string;
}

interface Employee {
  employeeId: number;
}

type Staff = Person & Employee;

let staffMember: Staff = {
  name: "张三",
  employeeId: 1234,
};

2. 字面量类型

字面量类型(Literal Types)是指使用具体的值作为类型,这些值可以是字符串、数字或布尔值。

type Direction = "Up" | "Down" | "Left" | "Right";

function move(direction: Direction) {
  console.log(`Moving ${direction}`);
}

move("Up");
move("Right");
// move("Forward"); // 错误:不能将类型“"Forward"”分配给类型“Direction”

3. 类型断言

类型断言(Type Assertion)允许你告诉编译器某个值的具体类型。

let someValue: unknown = "这是一个字符串";

let strLength: number = (someValue as string).length;

console.log(`字符串长度: ${strLength}`);

4. 类型兼容性

TypeScript 的类型兼容性基于结构子类型(structural subtyping),这意味着类型的兼容性是通过它们的成员来判断的。

interface Named {
  name: string;
}

let person: Named;
let animal = { name: "旺财", breed: "狗" };

person = animal; // 正确,animal 包含了 name 属性

5. 类型守卫

类型守卫(Type Guards)用于在运行时检查值的类型,以确保类型安全。

a. typeof 类型守卫

function padLeft(value: string, padding: number | string) {
  if (typeof padding === "number") {
    return Array(padding + 1).join(" ") + value;
  }
  if (typeof padding === "string") {
    return padding + value;
  }
  throw new Error(`Expected number or string, got ${typeof padding}`);
}

console.log(padLeft("Hello", 4)); // 输出: "    Hello"
console.log(padLeft("Hello", ">>> ")); // 输出: ">>> Hello"

b. instanceof 类型守卫

class Dog {
  bark() {
    console.log("汪汪");
  }
}

class Cat {
  meow() {
    console.log("喵喵");
  }
}

function makeSound(animal: Dog | Cat) {
  if (animal instanceof Dog) {
    animal.bark();
  } else {
    animal.meow();
  }
}

let myDog = new Dog();
let myCat = new Cat();

makeSound(myDog); // 输出: 汪汪
makeSound(myCat); // 输出: 喵喵

c. 自定义类型守卫

interface Fish {
  swim(): void;
}

interface Bird {
  fly(): void;
}

function isFish(pet: Fish | Bird): pet is Fish {
  return (pet as Fish).swim !== undefined;
}

function getPet(): Fish | Bird {
  return Math.random() < 0.5 ? { swim: () => console.log("游泳") } : { fly: () => console.log("飞行") };
}

let pet = getPet();

if (isFish(pet)) {
  pet.swim(); // 正确
} else {
  pet.fly(); // 正确
}

扩展知识点:类型映射(Mapped Types)

类型映射(Mapped Types)是一种生成新类型的方式,通常用于转换现有类型的属性。

type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

interface User {
  id: number;
  name: string;
}

let readonlyUser: Readonly<User> = {
  id: 1,
  name: "李四",
};

// readonlyUser.id = 2; // 错误,id 是只读属性

结语

通过本章的学习,你应该对 TypeScript 中的高级类型和类型操作有了更深入的理解。掌握这些高级特性将使你能够编写更加灵活和强大的代码。在下一章中,我们将继续探讨 TypeScript 中的接口和类,包括它们的定义、使用以及高级特性。务必掌握好每个概念,它们将为你后续学习 TypeScript 提供坚实的基础。

  • 22
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ziyu_jia

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值