0Pricing
TypeScript Academy · 课时

作为计算语言的类型

将类型系统理解为一种纯函数式语言。

作为计算语言的类型 是 CoddyKit 上的免费 TypeScript Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 TypeScript Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 TypeScript Academy 课程共包含 4 节课。

类型是一种语言

TypeScript 中并存着两种语言。一种是您已经熟悉的值级 JavaScript。另一种是类型层,它完全在编译时运行。在本课程中,您将学习如何用第二种语言进行编程。

类型系统是一种小型、纯粹的函数式语言。您向它输入类型,它就计算出类型作为输出。所有这些内容都不会保留到运行时。

type Greeting = "hello";
type Loud = Uppercase<Greeting>;
// Loud is "HELLO" - computed by the type system

类型输入,类型输出

泛型类型本质上是一个从类型映射到类型的函数。类型参数是参数,而函数体就是返回值。

下面的 Boxed 接收一个类型 T,并生成一个将其包装起来的对象类型。您可以将 T 理解为传入的参数。

type Boxed<T> = { value: T };

type A = Boxed<number>; // { value: number }
type B = Boxed<string>; // { value: string }

泛型就是函数

将值级函数与类型级函数进行比较。两者的形状几乎完全相同:输入参数,输出单一结果。

  • 值:const id = (x) => x
  • 类型:type Id<T> = T

类型级的 Id 只会返回您提供给它的内容。

type Id<T> = T;

type X = Id<boolean>; // boolean
type Y = Id<"abc">;  // "abc"

不产生运行时开销

类型层的所有内容都会在代码运行前被擦除。JavaScript 输出中不会留下任何类型计算的痕迹。无论类型多么复杂,运行中的程序都不会因此产生性能开销。

这就是类型级编程有时被称为免费的原因:它只会影响编译器,永远不会进入程序包。

type Pair<T> = [T, T];
const p: Pair<number> = [1, 2];
// Compiled JS is just: const p = [1, 2];
console.log(p);

多个参数

类型级函数可以像普通函数一样接收多个参数。这里的 Merge 接收两个对象类型并将它们合并。

可以这样理解:给定 A 和 B,返回一个包含两者全部属性的对象。

type Merge<A, B> = A & B;

type User = { id: number };
type Named = { name: string };
type NamedUser = Merge<User, Named>;
// { id: number; name: string }

参数默认值

类型参数可以拥有默认值,这与默认函数参数完全一样。如果调用方省略了该参数,就会使用默认值。

type List<T = string> = T[];

type A = List;        // string[]
type B = List<number>; // number[]

约束是守卫

带有 extends 的约束会限制可以传入哪些类型。它相当于在使用函数参数之前先验证参数。

HasId 只接受已经具有 id 属性的类型,因此函数体可以安全地读取该属性。

type GetId<T extends { id: number }> = T["id"];

type A = GetId<{ id: number; name: string }>; // number
// GetId<{ name: string }> would be a compile error

计算,而不只是注解

初学者只使用类型来为值标注。类型级编程则使用类型来计算结果。例如,内置的 ReturnType 工具类型会检查函数类型,并提取其结果类型。

type Fn = (a: number) => string;
type R = ReturnType<Fn>; // string

type Fn2 = () => boolean;
type R2 = ReturnType<Fn2>; // boolean

映射属性

映射类型可以转换对象类型的每个属性。这相当于类型语言中的循环。Stringify 会将每个值类型转换为 string。

type Stringify<T> = { [K in keyof T]: string };

type Input = { a: number; b: boolean };
type Out = Stringify<Input>; // { a: string; b: string }

纯粹且确定

类型语言是纯粹的:相同的输入始终产生相同的输出类型,并且没有副作用。它没有变更、没有 IO,也没有时间因素。正是这种纯粹性让类型级程序具有可预测性并且可以组合。

由于具有纯粹性,您可以像推理数学一样通过代入来推理类型。

type Square<T extends { area: number }> = T["area"];
// Always the same result for the same input shape

为何重要

掌握这第二种语言后,您就能编码出由编译器免费强制执行的规则:有效路由、穷举式分支、安全的字符串操作,以及不会被误用的应用程序接口。本课程的其余部分将逐步构建这套工具箱。

关键思维方式:类型语言中的类型是一个值,而泛型是一个函数。

type NonEmpty<T extends unknown[]> =
  T extends [unknown, ...unknown[]] ? T : never;
// Encodes a rule: the tuple must have at least one element

快速检查

测试您对类型作为计算语言的理解。

回顾

您已经学到,TypeScript 类型构成了一种在编译时运行的纯函数式语言。

  • 泛型就是函数:输入类型,输出类型。
  • 参数支持默认值和 extends 约束。
  • 映射类型会遍历属性。
  • 所有内容都会被擦除,因此不会产生运行时成本。

接下来,您将为这门语言加入一个条件语句:条件类型。

常见问题解答

「作为计算语言的类型」课时是免费的吗?

是的 — 「作为计算语言的类型」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 TypeScript Academy 课程的其余内容,请升级到 CoddyKit PRO。 TypeScript Academy 课程共包含 4 节课。

「作为计算语言的类型」这节课中我会学到什么?

将类型系统理解为一种纯函数式语言。 你通过在浏览器中直接运行的动手代码来练习 TypeScript Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 TypeScript Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 TypeScript Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「作为计算语言的类型」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 TypeScript Academy 课中编写并运行代码吗?

能。每节 TypeScript Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 作为计算语言的类型
  2. 类型级条件
  3. 类型级递归
  4. 可分配条件类型
← 返回 TypeScript Academy