reflect-metadata icon indicating copy to clipboard operation
reflect-metadata copied to clipboard

[email protected] [email protected] Reflect.getMetadata("design:type", target, propertyKey) == undefined ?

Open r1005410078 opened this issue 5 years ago • 7 comments

class Point {
  x!: number;
  y!: number;
}

class Line {
    private _p0!: Point;
    private _p1!: Point;

    @validate
    set p0(value: Point) { this._p0 = value; }
    get p0() { return this._p0; }

    @validate
    set p1(value: Point) { this._p1 = value; }
    get p1() { return this._p1; }
}

function validate<T>(target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<T>) {
    let set = descriptor.set;
    descriptor.set = function (value: T) {
      let type = Reflect.getMetadata("design:type", target, propertyKey);
      console.log(type) // undefined
      if (!(value instanceof type)) {
        throw new TypeError("Invalid type.");
      }
      // set.call(target, value);
    }
}
{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "resolveJsonModule": true
  },
  "include": [
    "src"
  ]
}

r1005410078 avatar Apr 03 '19 15:04 r1005410078

I'm having the same issue. It looks like it comes from here https://github.com/facebook/create-react-app/issues/6388 which leads to https://github.com/babel/babel/issues/9681.

Basically, Babel doesn't support emitDecoratorMetadata: https://babeljs.io/docs/en/babel-plugin-transform-typescript#typescript-compiler-options

magneticflux- avatar Apr 13 '19 01:04 magneticflux-

Had the same bug. But when i put

import "reflect-metadata";

as the first ever line in index.tsx with the following options in tsconfig.json

    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,

the issue was solved

kishaningithub avatar Sep 02 '19 04:09 kishaningithub

我是这样处理的...

    1. config-overrides.js 中开启.babelrc
const { useBabelRc } = require('customize-cra');

module.exports = override(
    useBabelRc()
);
    1. .babelrc中添加配置
{
    "plugins": [
      "babel-plugin-transform-typescript-metadata",
      ["@babel/plugin-proposal-decorators", { "legacy": true }],
      ["@babel/plugin-proposal-class-properties", { "loose": true }]
    ],
    "presets": [
      "@babel/preset-typescript"
    ]
}
    1. 把配置中需要的包下载一下

试了好多种方法 这种成功了 你试试看

liuxinya avatar Apr 02 '20 09:04 liuxinya

我是这样处理的...

* 1. config-overrides.js 中开启.babelrc
const { useBabelRc } = require('customize-cra');

module.exports = override(
    useBabelRc()
);
* 1. .babelrc中添加配置
{
    "plugins": [
      "babel-plugin-transform-typescript-metadata",
      ["@babel/plugin-proposal-decorators", { "legacy": true }],
      ["@babel/plugin-proposal-class-properties", { "loose": true }]
    ],
    "presets": [
      "@babel/preset-typescript"
    ]
}
* 1. 把配置中需要的包下载一下

试了好多种方法 这种成功了 你试试看

also good for react native

hanayashiki avatar Dec 05 '20 06:12 hanayashiki

我是这样处理的...

* 1. config-overrides.js 中开启.babelrc
const { useBabelRc } = require('customize-cra');

module.exports = override(
    useBabelRc()
);
* 1. .babelrc中添加配置
{
    "plugins": [
      "babel-plugin-transform-typescript-metadata",
      ["@babel/plugin-proposal-decorators", { "legacy": true }],
      ["@babel/plugin-proposal-class-properties", { "loose": true }]
    ],
    "presets": [
      "@babel/preset-typescript"
    ]
}
* 1. 把配置中需要的包下载一下

试了好多种方法 这种成功了 你试试看

also good for react native

I try it. it is working for me. Tips: you should import reflect metadata to every file top line I use react-native framework.

Domingowen avatar Mar 23 '21 02:03 Domingowen

Actually importing reflect-metadata in every file can cause this problem. If there are two different versions of reflect-metadata in your module tree then multiple versions of reflect-metadata may get loaded. If this happens, you may end up with a sort of "split brain" where some metadata is in one version and some is in the other.

Use npm ls reflect-metadata to see if you have multiple versions of reflect-metadata in your project.

Load reflect-metadata only once in the entrypoint file of the project. Do not import (or add a dependency to) reflect-metadata within a library.

rezonant avatar Mar 23 '21 03:03 rezonant

Another thing that I had to do to make @liuxinya's answer work for an application running using Metro builder was to start the application using the command npx react-native start --reset-cache. Without it, unnecessary caching of babel steps was leading to the configuration changes not working. Also, the project's babel.config.js was configured as follows:

module.exports =  {
  "plugins": [
    'babel-plugin-transform-typescript-metadata',
    ["@babel/plugin-proposal-decorators", { "legacy": true }],
    ["@babel/plugin-proposal-class-properties", { "loose" : true }]
  ],
  "presets": ["module:metro-react-native-babel-preset"]
}

ramanbedi1989 avatar Aug 14 '22 07:08 ramanbedi1989

Closing this as External as it seems to be an issue with Babel's emit.

Actually importing reflect-metadata in every file can cause this problem. If there are two different versions of reflect-metadata in your module tree then multiple versions of reflect-metadata may get loaded. If this happens, you may end up with a sort of "split brain" where some metadata is in one version and some is in the other.

Use npm ls reflect-metadata to see if you have multiple versions of reflect-metadata in your project.

Load reflect-metadata only once in the entrypoint file of the project. Do not import (or add a dependency to) reflect-metadata within a library.

This should hopefully no longer be an issue as of [email protected] or later as long as the minimum version of any copy of reflect-metadata in your dependencies is at least [email protected] or higher. In 0.1.12, reflect-metadata would no longer overwrite another copy that was present. As of 0.2.1, there is now a shared registry attached to Reflect that multiple copies will register with so that metadata is still reachable.

Also, the API surface of reflect-metadata is unlikely to change, so it should be safe to manually deduplicate multiple instances of the package in your dependency tree. You can use npm ls reflect-metadata to see which different versions are present, and you can use the "overrides" key in package.json to repoint stale dependencies to the more recent version.

rbuckton avatar Dec 14 '23 20:12 rbuckton