Vyhledávání na webu

javascript - Jak používat Reflection v TypeScriptu podobně jako v Javě?


Používám reflexi v Javě k získání některých informací z anotace TestNG, jako ve výše uvedeném ukázkovém kódu:

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

V současné době mám framework Jest s pluginem ozdobeným Jest, který pomáhá při používání anotací.

Jak mohu replikovat stejnou metodu reflexe v Javě, ale v TypeScriptu, abych získal tyto informace z anotací?

Odpověď č. 1

Podívejte se prosím na dekorátory TypeScriptu + Reflect Metadata API, které lze také povolit pro TS kompilátor. Nepracuje to přesně jako Java, ale i tak můžete shromáždit potřebné informace o anotovaných entitách. Malý příklad, jak shromáždit anotované třídy:

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);

Odpověď č. 2

Vyzkoušejte mou knihovnu tst-reflect. Jedná se o poměrně pokročilý systém Reflection pro TypeScript (používající vlastní plugin pro transformaci TypeScriptu).

To by mělo být ekvivalentem vašeho kódu v Javě:

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);
}

Výstup

foo in A
bar in B

Zkontrolujte synopsi. Jste schopni vytvářet instance těchto typů (i když jsou z různých souborů) a volat tyto metody. Také tyto dekorátory mohou mít argumenty, takže budete schopni filtrovat metody se stejnými dekorátory, ale s různými argumenty.

tst-reflect je stále ve vývoji, takže globální vyhledávání typů vyžaduje tyto dekorátory @reflect nebo vlastní dekorátory s JSDoc tagem @reflect; důvodem je optimalizace velikosti generovaných metadat. Ale existuje problém s rozšířením konfigurace o "include" glob patterny, které zahrnou všechny typy ze všech modulů, které těmito globy odpovídají.

PS: Podívejte se na wiki konfigurace a použijte tuto konfiguraci:

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
        }
    }
}