首先,让我们对值级编程语言和类型级编程语言进行一个重要的区分。值级编程语言让我们编写将在生产环境中运行的代码,并为用户提供有用的东西。但是,类型语言在代码触达我们的用户之前就被完全删除了。它只是用来帮助 TypeScript 在发布之前确保代码不包含错误。
JavaScript 没有类型,所以自然地所有的 JavaScript 都是值级层面的代码$^{1}$:
// A simple Javascript function:
function sum(a, b) {
return a + b;
}
TypeScript 允许我们在 JavaScript 中添加类型注释,以确保我们编写的 sum
函数除了传入数字以外,不会被调用:
// Using type annotations:
function sum(a: number, b: number): number {
return a + b;
}
但是 TypeScript 的类型系统要比这强大得多。现实中我们编写的代码有时需要是泛型的,并接受我们事先所未知的类型。
在这种情况下,我们可以在尖括号 <A,B,...>
中定义类型参数,并用 a: A
将它们赋给实际值参数。然后,我们可以将类型参数传递给一个类型级函数,该函数根据输入的类型计算输出的类型:
// Using type level programming:
function genericFunction<A, B>(a: A, b: B): DoSomething<A, B> {
return doSomething(a, b);
}
这就是所谓的类型级别的编程!DoSomething<A,B>
是用一种特殊的编程语言编写的类型级函数,它不同于我们用来表示值的语言,但同样强大。让我们将这种语言称之为类型级别的 TypeScript。
// This is a type-level function:
type DoSomething<A, B> = ...
// This is a value-level function:
const doSomething = (a, b) => ...
类型级 TypeScript 是一种最小化的纯函数式语言。
该定义中的术语“函数式”指的是函数式编程,这是一个您可能以前听说过的概念。类型级 TypeScript 是函数式的,因为函数是这种语言的主要抽象手段。我们将一直使用函数。
在类型世界中,函数称为泛型类型:它们接受一个或多个类型参数并返回单个输出类型。下面是一个函数的简单示例,该函数接受两个类型参数并将它们封装在一个元组之中:
type SomeFunction<A, B> = [A, B];
/* ---- ------
^ \\
type return type
parameters
\\-------------------------/
^
Generic
*/
类型级别的 TypeScript 没有很多特性。毕竟它是专门被设计用来为你的代码添加类型的!也就是说,它确实有足够的特性(几乎)具备图灵完备性,这意味着您可以用它解决任意复杂度的问题。
下面是你可以用类型级别的 TypeScript 做的一些事情:
if
/else
关键字)。var
/let
关键字)。