18

I would like to be access the type information on a variable declaration that I want to decorate:

@decorator
foo: Foo;

From the decorator, can I somehow access Foo?

2 Answers 2

35

You should be able to do it, but you'll need to use reflect-metadata.

There's an example here: Decorators & metadata reflection in TypeScript: From Novice to Expert which seems to be exactly what you're after:

function logType(target : any, key : string) {
    var t = Reflect.getMetadata("design:type", target, key);
    console.log(`${key} type: ${t.name}`);
}

class Demo{ 
    @logType
    public attr1: string;
}

Should print:

attr1 type: String

Sign up to request clarification or add additional context in comments.

4 Comments

When I do import 'reflect-metadata'; and import 'zone.js/dist/zone', I get the message Cannot resolve all parameters for 'App'(?, ?, ?). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'App' is decorated with Injectable.. Any ideas? I am on RC1.
Is that compilation error or runtime? I'm able to compile the above example with no issues, so it must be something to do with this zone.js thing. I added import "zone.js/dist/zone" and recompiled with no issues as well.
Thanks Nitzan for providing useful link. I was wandering for the whole day
BTW. To make the 'design:type' work make sure add "emitDecoratorMetadata": true in the tsconfig.json
0

Providing the solution using Vite and React TypeScript.

  1. Add appropriate decorator compiler options to your tsconfig.json
{
   "compilerOptions": {
       "experimentalDecorators": true,
       "emitDecoratorMetadata": true,
       /* ... */
   }
}
  1. Install babel plugin dependencies
npm install @babel/plugin-proposal-class-properties
npm install @babel/plugin-proposal-decorators
npm install @babel/preset-typescript
npm install babel-plugin-transform-typescript-metadata
  1. Apply the necessary babel configuration to your vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [
        react({
            babel: {
                plugins: [
                    "babel-plugin-transform-typescript-metadata",
                    ["@babel/plugin-proposal-decorators", { legacy: true }],
                    ["@babel/plugin-proposal-class-properties", { loose: true }],
                ],
                presets: ["@babel/preset-typescript"],
            },
        }),
    ],
});

Now you can test the solution:

function Decorator(target: any, key: string) {
    const type = Reflect.getMetadata("design:type", target, key);
    console.log(`Field: ${key} | Type: ${type.name}`);
}

class MyClass {
    @Decorator field1!: string;
    @Decorator field2!: number;
    @Decorator field3!: boolean;
}

// Field: field1 | Type: String
// Field: field2 | Type: Number
// Field: field3 | Type: Boolean

1 Comment

Tried with Vue (I don't think that really matters), but unfortunately this setup does not work. :/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.