如何像在java中一样在typescript中使用Reflection?

问题描述 投票:0回答:2

我在 Java 中使用反射从 TestNG 注释中获取一些信息,如下面的代码片段所示:

Reflections reflections = new Reflections("", new MethodAnnotationsScanner())
Set<Method> annotated = reflections.getMethodsAnnotatedWith(Test.class)

目前,我有一个 jest 框架,带有一个 jest 装饰的插件,可以帮助使用注释。

如何在 Java 中复制相同的反射方法,但在打字稿中从注释中收集此信息?

javascript java reflection jestjs ts-jest
2个回答
3
投票

请查看 Typescript 的 Decorators + Reflect Metadata API,它也可以为 TS 编译器启用。它的工作方式与 Java 不完全相同,但您仍然可以收集有关带注释的实体的所需信息。如何收集带注释的类的小示例:

const myTypes: any[] = []

@annotation
class MyClass {
  type = "report";
  title: string;
 
  constructor(t: string) {
    this.title = t;
  }
}

function annotation(constructor: Function) {
    myTypes.push(constructor)
}

console.log('All annotated classes', myTypes);


2
投票

尝试我的库tst-reflect。 它是非常先进的 TypeScript 反射系统(使用自定义 TypeScript 转换器插件)。

这应该相当于您的 Java 代码:

import {
    reflect,
    Type
} from "tst-reflect";

// Some decorator...
function test(_, __)
{
}

@reflect()
class A
{
    @test
    foo()
    {
        return 0;
    }

    bar()
    {
        return "lorem ipsum";
    }
}

@reflect()
class B
{
    @test
    bar()
    {
        return "lorem ipsum";
    }
}

@reflect()
class C
{
    baz()
    {
        return "lorem ipsum";
    }
}

const decoratedMethods = Type.getTypes()
    .flatMap(type => type.getMethods().map(method => ({ method, type })))
    .filter(entry => entry.method.getDecorators().some(decorator => decorator.name == "test"));

for (let entry of decoratedMethods)
{
    console.log(entry.method.name, "in", entry.type.name);
}

输出

foo in A
bar in B

检查概要。 您可以创建这些类型的实例(即使它们来自不同的文件)并调用这些方法。 这些装饰器也可以有参数,这样您就可以使用相同的装饰器但不同的参数来过滤方法。

tst-reflect
仍在开发中,因此类型的全局查找需要那些
@reflect
装饰器或带有
@reflect
JSDoc 标签的自定义装饰器;原因是生成的元数据的大小优化。但是有一个问题可以通过“包含”全局模式来扩展配置,该模式将包括与该全局匹配的所有模块中的所有类型。

PS:查看配置wiki并使用此配置:

tsconfig.json

{
    "compilerOptions": {
        // your options...

        // ADD THIS!
        "plugins": [
            {
                "transform": "tst-reflect-transformer"
            }
        ]
    },
    // ADD THIS!
    "reflection": {
        "metadata": {
            "type": "typelib" // this mode will generate and auto-import library with generated reflection metadata
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.