作为计算语言的类型
将类型系统理解为一种纯函数式语言。
作为计算语言的类型 是 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 反馈 — 无需本地设置。