TypeScript 学习笔记(二):深入类型系统

1. 引言

在上一篇学习笔记中,我们介绍了 TypeScript 的基础知识,包括类型注解、接口、类和函数。本篇将深入探讨 TypeScript 的类型系统,学习如何使用高级类型、泛型和类型推断等特性,以便在复杂应用场景中更好地利用 TypeScript。

2. 高级类型

2.1 交叉类型

交叉类型(Intersection Types)用于将多个类型合并为一个类型,它表示一个对象可以同时具有这些类型的所有成员。

interface Person {
    name: string;
    age: number;
}

interface Employee {
    employeeId: number;
}

type PersonEmployee = Person & Employee;

let personEmployee: PersonEmployee = {
    name: "John",
    age: 30,
    employeeId: 12345
};
2.2 联合类型

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

let value: string | number;
value = "Hello";
value = 42;

function format(value: string | number): string {
    if (typeof value === "string") {
        return value.toUpperCase();
    }
    return value.toFixed(2);
}
2.3 类型别名

类型别名(Type Aliases)用于为类型创建一个新名字,可以是基础类型、联合类型、交叉类型甚至是对象类型。

type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;

function getName(n: NameOrResolver): Name {
    if (typeof n === "string") {
        return n;
    }
    return n();
}

3. 泛型

泛型(Generics)允许我们在定义函数、接口或类时不预先指定具体的类型,而是在使用时再指定类型,从而提高代码的通用性和可重用性。

3.1 泛型函数

泛型函数可以在函数名后面添加一个尖括号来定义泛型参数。

function identity<T>(arg: T): T {
    return arg;
}

let output1 = identity<string>("myString");
let output2 = identity<number>(100);
3.2 泛型接口

接口也可以使用泛型来定义。

interface GenericIdentityFn<T> {
    (arg: T): T;
}

function identity<T>(arg: T): T {
    return arg;
}

let myIdentity: GenericIdentityFn<number> = identity;
3.3 泛型类

类也可以使用泛型来定义。

class GenericNumber<T> {
    zeroValue: T;
    add: (x: T, y: T) => T;
}

let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = (x, y) => x + y;
3.4 泛型约束

有时候我们希望限制泛型的类型,这时候可以使用泛型约束。

interface Lengthwise {
    length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);
    return arg;
}

// 正确
loggingIdentity({ length: 10, value: 3 });

// 错误,类型没有 length 属性
// loggingIdentity(3);

4. 类型推断

TypeScript 会根据代码的上下文自动推断类型,从而减少显式的类型注解。

let x = 3; // x 被推断为 number 类型

function add(a: number, b: number) {
    return a + b; // 返回值被推断为 number 类型
}

let result = add(2, 5); // result 被推断为 number 类型

5. 类型守卫

类型守卫(Type Guards)用于在运行时检查类型,从而在代码中进行类型保护。

function isNumber(x: any): x is number {
    return typeof x === "number";
}

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

6. 映射类型

映射类型(Mapped Types)用于根据已有类型创建新的类型。它们经常与类型别名和索引签名一起使用。

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

interface Person {
    name: string;
    age: number;
}

let readonlyPerson: Readonly<Person> = {
    name: "John",
    age: 30
};

// readonlyPerson.age = 31; // Error: Cannot assign to 'age' because it is a read-only property.

7. 实用工具类型

TypeScript 提供了一些实用工具类型,用于处理类型操作。

  • Partial<T>:将类型 T 的所有属性设为可选。
  • Required<T>:将类型 T 的所有属性设为必选。
  • Readonly<T>:将类型 T 的所有属性设为只读。
  • Pick<T, K>:从类型 T 中选择部分属性构成新的类型。
  • Omit<T, K>:从类型 T 中排除部分属性构成新的类型。
interface Person {
    name: string;
    age: number;
    address?: string;
}

let partialPerson: Partial<Person> = {
    name: "John"
};

let requiredPerson: Required<Person> = {
    name: "John",
    age: 30,
    address: "123 Main St"
};

let readonlyPerson: Readonly<Person> = {
    name: "John",
    age: 30
};

// readonlyPerson.age = 31; // Error

let pickedPerson: Pick<Person, "name" | "age"> = {
    name: "John",
    age: 30
};

let omittedPerson: Omit<Person, "address"> = {
    name: "John",
    age: 30
};

8. 总结

在本篇学习笔记中,我们深入探讨了 TypeScript 的高级类型系统,包括交叉类型、联合类型、类型别名、泛型、类型推断、类型守卫、映射类型和实用工具类型。通过这些高级特性,我们可以编写出更强大、灵活和可维护的代码。

下一篇学习笔记将介绍 TypeScript 中的模块系统和命名空间,以及如何与 JavaScript 进行互操作。希望你能继续关注本系列的学习笔记,进一步提升 TypeScript 编程技能。

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Evaporator Core

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

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

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

打赏作者

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

抵扣说明:

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

余额充值