首先,让我们对值级编程语言和类型级编程语言进行一个重要的区分。值级编程语言让我们编写将在生产环境中运行的代码,并为用户提供有用的东西。但是,类型语言在代码触达我们的用户之前就被完全删除了。它只是用来帮助 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 做的一些事情: