TypeScript高级数据类型 | 青训营笔记

116 阅读4分钟

这是我参与「第五届青训营」伴学笔记创作活动的第10天。

一、本堂课重点内容

通过基础数据类型快速进行高级类型的定义,通过一种基本类型衍生出很多高级类型。在类型联动中就无需编写很多重复代码。

  • 联合/交叉类型
  • 类型保护与类型守卫
  • 函数返回值类型
  • 工程应用

二、详细知识点介绍

联合/交叉类型

类型保护与类型守卫

联合类型:IA|IB,联合类型表示一个只可以是几种类型之一,联合类型,联合泛型,联合接口通用,如:

type strNum = string | number;
const a: strNum = 1;
const b: strNum = "1";

交叉类型:IA&IB,多种类型叠加到一起成为一种类型,包含了所需的所有类型的特性,交叉类型,交叉泛型,交叉接口通用,如:

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

interface B {
    name: string;
    height: number;
}

const a: A & B = {
    name: "alice",
    age: 16,
    height: 160
};

类型保护与类型守卫

类型保护

访问联合类型时,只能访问联合类型中的交集部分,而无法访问到独有的部分,但在JavaScript是可以使用的,TypeScript会报错。

类型保护是指缩小类型的范围,在一定的块级作用域内由编译器推导其类型,提示并规避不合法的操作,提高代码质量。

类型保护就是一些表达式,它们会在运行时检查以确保在某个作用域里的类型。

我们可以通过typeof、instanceof、in、is和字面量类型将代码分割成范围更小的代码块,在这一块中,变量的类型是确定的。

类型守卫

类型守卫是一种TypeScript技术,用于获取变量类型信息,通常使用在条件块语句中。类型守卫是返回布尔值的常规函数,接受一个类型并告诉TypeScript是否可以缩小到更具体的类型。类型守卫具有唯一的属性,可以确保测试的值返回的是布尔值类型。

TypeScript使用了一些内置的JavaScript操作符,比如typeof、instanceof和in操作符,这些操作符用于确定一个对象是否包含属性。类型守卫可以让你指导TypeScript编译器在特定的上下文中推断出变量的特定类型,确保参数的类型与你指定的一致。

详见参考文档。

关键字keyof和in

keyof

相当于取值对象中的所有key组成的字符串字面量。

TypeScript允许我们遍历某种类型的属性,并通过keyof操作符提取其属性的名称。

keyof操作符可以用于获取某种类型的所有键,其返回类型是联合类型。

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

type K1 = keyof Person; // "name" | "age" | "location"
type K2 = keyof Person[];  // number | "length" | "push" | "concat" | ...
type K3 = keyof { [x: string]: Person };  // string | number

in

in的右侧一般会跟一个联合类型,使用in操作符可以对该联合类型进行迭代。 其作用类似JS中的for...in或者for...of

type Animals = 'pig' | 'cat' | 'dog'
type animals = {
    [key in Animals]: string
}
// type animals = {
//     pig: string; //第一次迭代
//     cat: string; //第二次迭代
//     dog: string; //第三次迭代
// }

三、实践实习例子

联合&交叉类型

为bookList定义类型

const bookList = [{
    author: "Alice",
    type: "history",
    date: "2023-01-23"
}, {
    author: "Bob",
    type: "story",
    theme: "love"
}];
type IBookList = Array<{
    author: string
} & ({
    type: "history",
    range: string
} | {
    type: "story",
    theme: string
})>

类型守卫

联合类型+类型保护=自动类型推断,在上面的例子中,通过联合&交叉类型定义一本书的类型为IBookItem,则可通过以下方式实现自动类型推断:

function logBook(book: IBookItem) {
    if (book.type === "history") {
        console.log(book.date);
    } else {
        console.log(book.theme);
    }
}

TypeScript的工程应用

Webpack

  • 配置Webpack loader,把Webpack不能识别的文件转为Webpack能识别的
    • 相关loader有awesome-typescript-loader或babel-loader等
  • 配置tsconfig.js文件,约束项目行为
  • 运行Webpack,启动/打包
  • loader处理ts文件时,会进行编译和类型检查

NodeJS

通过tsc编译ts文件得到js,可以通过npm命令进行流程化的处理。

四、课后个人总结

本节课学习了TypeScript的一些高级特性,为提高代码可阅读性和可维护性,可以通过TypeScript基本类型构建出多种多样的高级类型,实现复杂多样的功能需求。本节课以联合/交叉类型、类型保护与类型守卫等,介绍了TS常见的高级特性,很多高级特性都借助泛型实现,可见泛型是实现TS多态性的重要方式。

本节课还介绍了TypeScript的工程应用,以Webpack和NodeJS为例介绍了TS在生产环境的应用,希望以后继续学习研究。

五、参考链接

TypeScript基础之类型保护_夜已如歌_ok的博客-CSDN博客

在 TypeScript 中使用类型守卫的 5 种方式,你都知道吗 - 腾讯云开发者社区-腾讯云 (tencent.com)

TypeScript学习之keyof类型操作符 - 掘金 (juejin.cn)

【TypeScript】keyof & in 关键字详解 - 掘金 (juejin.cn)

‍‌‬‌⁣⁤⁢⁢​⁣⁢​⁤⁤⁤​‌⁣⁣⁤‍⁡⁢​⁣⁣​‌⁡​⁡⁡‍⁡⁡​⁡⁤‌​⁢⁢‬⁣‍‬TypeScript入门.pptx - 飞书云文档 (feishu.cn)