Search code examples
typescriptvitereflect-metadata

Why can't reflect-metadata be used in vite


import "reflect-metadata"

function validate(target: any) {
  let paramtypes = Reflect.getMetadata("design:paramtypes", target);
  console.log(paramtypes);  // undefined
}

@validate
class Log {
  constructor(public readonly xx: string) {}
}

Hit me to start the server, and when I opened the webpage, I found that paramtypes was undefined

tsconfig.json

{
  "compilerOptions": {
    "target": "ESNext",
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "allowJs": false,
    "skipLibCheck": false,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  },
  "include": ["./src"]
}

Solution

  • Vite uses ESBuild which doesn't support "emitDecoratorMetadata" in tsconfig, since ESBuild doesn't have its own type system implemented. Refer to this vitejs/vite#788 for more details on this topic.

    However, there are workarounds to this issue. One approach I took was explicitly disabling ESBuild and used SWC instead. You can find more details regarding that on this demo. Here is its vite config file:

    import typescript from "@rollup/plugin-typescript";
    import swc from "rollup-plugin-swc";
    
    // import typescript from "rollup-plugin-typescript2";
    
    export default defineConfig({
        plugins: [
            swc({
                jsc: {
                    parser: {
                        syntax: "typescript",
                        // tsx: true, // If you use react
                        dynamicImport: true,
                        decorators: true,
                    },
                    target: "es2021",
                    transform: {
                        decoratorMetadata: true,
                    },
                },
            }),
        ],
        esbuild: false,
    });
    

    SWC is a fast alternative to ESBuild, having implemented its own type system, it can emit decorator metadata without any issue.