javascript - Ako používať Reflection v TypeScripte podobne ako v Jave?


Používam refleksiu v Jave na získanie niektorých informácií z anotácie TestNG, ako je to v kóde nižšie:

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

V súčasnosti mám framework Jest s plug-inom dekorovaným Jest, ktorý pomáha pri používaní anotácií.

Ako môžem replikovať tú istú metódu reflexie v Jave, ale v TypeScripte, aby som získal tieto informácie z anotácií?

Odpoveď č. 1

Pozrite si, prosím, dekorátory Typescriptu + Reflect Metadata API, ktoré je možné tiež povoliť pre TS kompilátor. Nefunguje presne ako Java, ale stále môžete zhromaždiť požadované informácie o anotovaných entitách. Malý príklad, ako zhromaždiť anotované triedy:

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

Odpoveď č. 2

Vyskúšajte moju knižnicu tst-reflect. Je to pomerne pokročilý reflektujúci systém pre TypeScript ().

Toto by malo byť ekvivalentom vášho Java kódu:

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

Skontrolujte synopsu. Ste schopní vytvárať inštancie týchto typov (aj keď sú z rôznych súborov) a volat tie metódy. Tiež tieto dekorátory môžu mať argumenty, takže budete schopní filtrovať metódy s rovnakými dekorátormi, ale rôznymi argumentmi.

tst-reflect je stále vo vývoji, takže globálne vyhľadávanie typov vyžaduje použitie týchto dekorátorov @reflect alebo vlastných dekorátorov s JSDoc tagom @reflect; dôvodom je optimalizácia veľkosti generovaných metadát. Ale existuje problém s rozšírením konfigurácie pomocou glob vzorov „include“, ktoré zahrnú všetky typy zo všetkých modulov, ktoré tieto globy zodpovedajú.

PS: Pozrite si konfiguračnú wiki a použite túto konfiguráciu:

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