不久前,我在推特上看到了一个完全在类型系统中实现Flappy Bird的人,我看了代码,它是Typescript 的,但我不能理解太多.

类型用于添加类型是什么的显式指示,泛型使类型系统功能更强大,但就我所知,TypeScrip中的类型系统不能执行实际代码,那么这是如何实现的?

推荐答案

类型脚本类型不能在运行时"执行实际代码",但它们仍然可以表达关系和转换.它实际上很像函数式编程.

type Transform<T> = {
  [K in keyof T]: {
    value: T[K]
  }
}
type A = { foo: string, bar: string }
type B = Transform<A>
// { foo: { value: string }, bar: { value: string } }

在这个愚蠢的例子中,Transform可以被认为是一个接受名为T的参数的"函数",该参数"返回"从T派生的另一个类型.

这有点像是以compile time的速度运行的程序,而不是运行时.上面的类型脚本代码编译为一个空文件,因为它不包含可执行的运行时代码.

因此,上面的代码可以被描述为"完全在类型系统内".

现在,如果它从未触及可执行代码,那么这是useful吗?大概不会吧.但这类东西是一个展示TypeScrip用类型描述复杂行为的能力的窗口.


我见过的最好的例子之一是ts-sql,它实现了一个SQL数据库,并完成了SQL查询解析.

import { Query } from "@codemix/ts-sql";

const db = {
  things: [
    { id: 1, name: "a", active: true },
    { id: 2, name: "b", active: false },
    { id: 3, name: "c", active: true },
  ],
} as const;

type ActiveThings = Query<
  "SELECT id, name AS nom FROM things WHERE active = true",
  typeof db
>;

// ActiveThings is now equal to the following type:
type Expected = [{ id: 1; nom: "a" }, { id: 3; nom: "c" }];

您提供一个数据库状态,它是一种类型.然后使用字符串文字类型对其进行查询,这将返回更多类型.因此,就像我上面的简单示例一样,您可以将类型传递给其他类型,以输出更多的类型,这些类型是输入类型的逻辑派生.

那么,这在真正的应用程序中有用吗?大概不会吧.不过,这真的很酷!

Typescript相关问答推荐

如何根据服务响应构建子路由

Typescript:假设foo不在类型栏中,而它在:如何调试

输入具有相同键但值类型不同的对象

Angular 17 Select 错误core.mjs:6531错误错误:NG 05105:发现意外合成监听器@transformPanel.done

需要使用相同组件重新加载路由变更数据—React TSX

我用相同的Redux—Toolkit查询同时呈现两个不同的组件,但使用不同的参数

在NextJS中获得Spotify Oauth,但不工作'

Vue SFC中的多个脚本块共享导入的符号

TypeScrip:强制使用动态密钥

TypeScrip错误:为循环中的对象属性赋值

如何按属性或数字数组汇总对象数组

自动通用回调

使用来自API调用的JSON数据的Angular

如何将通用接口的键正确设置为接口的键

创建一个函数,该函数返回一个行为方式与传入函数相同的函数

在类型脚本中创建显式不安全的私有类成员访问函数

基于闭包类型缩小泛型类型脚本函数的范围

仅当类型为联合类型时映射属性类型

我的类型谓词函数不能像我预期的那样工作.需要帮助了解原因

如何为对象数组中的每个条目推断不同的泛型