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