Hookyns / tst-reflect

Advanced TypeScript runtime reflection system
MIT License
338 stars 11 forks source link

Can't get `getType<T>()` to work #77

Closed 3p3r closed 1 year ago

3p3r commented 1 year ago

Hello! Awesome project. Thank you!

I have a question, not sure if I am hitting a setup bug, but I am using tst-reflect through webpack and ttypescipt. I have this snippet:

interface IFoo {}
class Foo implements IFoo {}

const foo = new Foo();
getType<Foo>();
getType<typeof foo>();
getType<IFoo>();

I can see my source is instrumented with reflection data correctly, but these calls are all compiling to empty getType() calls. Am I doing something wrong?

3p3r commented 1 year ago

If it helps, I am using ttsc.transpileModule directly in code.

Hookyns commented 1 year ago

Hi @3p3r, here is an StackBlitz example with regular Webpack setup that works fine.

Can you please post a repro with your usage of ttsc.transpileModule?

3p3r commented 1 year ago

Thanks for the quick response! So I am writing a new webpack loader for my project that happens to use tst-reflect in it. I am using the following snippet:

import ttsc from "ttypescript";
const compiledTSX = `...`; // some source
console.log(ttsc.transpileModule(compiledTSX, {
    compilerOptions: {
      configFilePath: path.resolve(process.cwd(), "tsconfig.json"),
      target: ttsc.ScriptTarget.ESNext,
      jsx: ttsc.JsxEmit.ReactJSX,
      jsxImportSource: "jsx",
      experimentalDecorators: true,
      module: ttsc.ModuleKind.NodeNext,
      allowJs: true,
      esModuleInterop: true,
      alwaysStrict: true,
      skipDefaultLibCheck: true,
      skipLibCheck: true,
      typeRoots: ["node_modules/@types"],
      // @ts-expect-error
      plugins: [{ transform: require.resolve("tst-reflect-transformer") }],
    },
  }).outputText)

The tsconfig.json file on disk is just an empty file. Is this a supported use-case?

Hookyns commented 1 year ago

@3p3r

I played with it a little...

The issue is in transpileModule inside typescript itself. It does not load declarations of modules etc. It only transpile given module. getType<>() calls were not recognized as our getType calls so we ignored them. Recognition is based on declaration.

I did some changes, so every getType<T>() without declaration (typechecker returns error for such function), called exactly with one type argument, will be considered as our. Here is new demo.

Included in tst-reflect-transformer@0.12.5.

3p3r commented 1 year ago

Thanks so much for the detailed response. I also found https://ts-morph.com/ in the meantime that has worked with tst-reflect and doing in-memory compilation. Using ts-morph is admittedly less confusing than the original compiler API.