【问题标题】:Typescript: Implementing a transformer to access types at run-timeTypescript:实现转换器以在运行时访问类型
【发布时间】:2021-07-22 12:26:18
【问题描述】:

TSC 将 TS 代码编译为 JS 后,类型被移除,不再可用。

但是,原则上,应该可以通过使用 webpack/typescript/Vite 转换器使这些类型在运行时可用。

有人做到了吗?

type Data = {
  name: string;
  age: number;
};

// How can we implement `getType()`?
console.log(getType<Data>());
// It should print:
// { name: 'string', age: 'number' }

在编译类型中,Data 的类型是已知的,因此应该可以(尽管不容易)实现一个转换器,使该类型在运行时可用。

这将支持大量用例,例如 IO 验证。

对于我的用例,我不需要泛型等高级类型。我只需要类型:对象、数组、字符串、数字和日期。

上下文:我正在构建一个 RPC 实现 (https://github.com/brillout/wildcard-api)。

编辑:我不是在寻找像 zod 这样的东西,你用 zod 定义模式,然后推断 TypeScript 类型。我的用户使用 TypeScript 直接 定义他们的类型,我需要在运行时知道这些类型。所以我确实需要一个编译时转换器。

【问题讨论】:

  • 有很多运行时验证器:ajv, joi, v8n, validate.js。您应该为此目的使用 typescript 自定义类型保护
  • @captain-yossarian 这些是 JavaScript 验证器。我想要的是通过 only 使用我用 TypeScript 定义的类型进行运行时验证。 (这里的最终目标是自动为我的 Wildcard API 用户进行验证。)
  • 但类型在编译后被移除
  • @brillout 是的,旨在实现这一目标以及更多。见this堆栈溢出答案:)
  • @CarloCorradini 整洁。尽管它仅适用于类属性,因为函数装饰器仍在进行中。 { name: string; age: number } 等复合类型似乎仍在进行中。当两者都实现时,我相信Reflect 对我来说将是一个可行的选择......整洁并感谢您的指针。

标签: typescript


【解决方案1】:

ts-runtime 之类的东西吗?这与您的问题描述的不完全一样,但请看一下。

您的输入代码:

type Data = {
  name: string;
  age: number;
};

它输出:

import t from "ts-runtime/lib";

const Data = t.type(
  "Data",
  t.object(
    t.property("name", t.string()),
    t.property("age", t.number())
  )
);

然后你可以运行:

t.type(Data).assert({/* ... obj to evaluate ... */})

【讨论】:

    【解决方案2】:

    typescript-rtti 项目针对给定编译的所有类型元数据全面执行此操作(并且当调用者和被调用者都使用转换器编译时跨包工作)。您可以通过浏览器在https://typescript-rtti.org/进行测试

    (免责声明:我是作者)

    【讨论】:

      【解决方案3】:

      试试tst-reflect。 它是非常先进的 TypeScript 反射系统,灵感来自 C# 反射。

      import { getType, Type } from "tst-reflect";
      
      type Data = {
        name: string;
        age: number;
      };
      
      const typeofData: Type = getType<Data>();
      
      const objWithProps = typeofData.getProperties().reduce((res, prop) => {
        res[prop.name] = prop.type.name;
        return res;
      }, {} as any);
      
      console.log(objWithProps);
      

      输出

      { name: 'String', age: 'Number' }
      

      【讨论】:

        猜你喜欢
        • 2015-11-17
        • 2022-01-16
        • 1970-01-01
        • 2022-07-27
        • 1970-01-01
        • 1970-01-01
        • 2017-08-24
        • 1970-01-01
        相关资源
        最近更新 更多