All Projects → leonardfactory → Babel Plugin Transform Typescript Metadata

leonardfactory / Babel Plugin Transform Typescript Metadata

Licence: mit
Babel plugin to emit decorator metadata like typescript compiler

Programming Languages

javascript
184084 projects - #8 most used programming language
typescript
32286 projects

Projects that are alternatives of or similar to Babel Plugin Transform Typescript Metadata

Compiled
A familiar and performant compile time CSS-in-JS library for React.
Stars: ✭ 1,235 (+769.72%)
Mutual labels:  babel, babel-plugin
Jsx Control Statements
Neater If and For for React JSX
Stars: ✭ 1,305 (+819.01%)
Mutual labels:  babel, babel-plugin
Modify Babel Preset
💫 Create a modified babel preset based on an an existing preset.
Stars: ✭ 85 (-40.14%)
Mutual labels:  babel, babel-plugin
Babel Plugin Captains Log
Babel plugin that injects helpful details into console statements
Stars: ✭ 80 (-43.66%)
Mutual labels:  babel, babel-plugin
Babel Plugin Mobx Deep Action
Reduces `action` and `runInAction` boilerplates
Stars: ✭ 110 (-22.54%)
Mutual labels:  babel-plugin, decorators
Babel Plugin Optimize Clsx
Babel plugin to optimize the use of clsx, classnames, and other libraries with a compatible API
Stars: ✭ 80 (-43.66%)
Mutual labels:  babel, babel-plugin
Idx.macro
a 'babel-macros' version of 'babel-plugin-idx'
Stars: ✭ 90 (-36.62%)
Mutual labels:  babel, babel-plugin
Tinker.macro
Evaluate Laravel code at build-time, via Laravel Tinker
Stars: ✭ 56 (-60.56%)
Mutual labels:  babel, babel-plugin
Js Proposal Algebraic Effects
📐Let there be algebraic effects in JS
Stars: ✭ 110 (-22.54%)
Mutual labels:  babel, babel-plugin
Babel Plugin Jsx Adopt
Stars: ✭ 94 (-33.8%)
Mutual labels:  babel, babel-plugin
Astexplorer.app
https://astexplorer.net with ES Modules support and Hot Reloading
Stars: ✭ 65 (-54.23%)
Mutual labels:  babel, babel-plugin
Babel Plugin Polished
Compile polished helper functions at build time
Stars: ✭ 133 (-6.34%)
Mutual labels:  babel, babel-plugin
Sowing Machine
🌱A React UI toolchain & JSX alternative
Stars: ✭ 64 (-54.93%)
Mutual labels:  babel, babel-plugin
Catom
A 0 runtime CSS in JS library
Stars: ✭ 84 (-40.85%)
Mutual labels:  babel, babel-plugin
Babel Plugin Partial Application
[DEPRECATED] Please use https://github.com/citycide/param.macro
Stars: ✭ 60 (-57.75%)
Mutual labels:  babel, babel-plugin
Generator Babel Plugin
Babel Plugin generator for Yeoman
Stars: ✭ 88 (-38.03%)
Mutual labels:  babel, babel-plugin
Babel Plugin Root Import
Add the opportunity to import modules by the root path
Stars: ✭ 1,084 (+663.38%)
Mutual labels:  babel, babel-plugin
Babel Plugin Css Prop
Babel plugin to transpile `css` prop to a styled component. (Experimental)
Stars: ✭ 56 (-60.56%)
Mutual labels:  babel, babel-plugin
Babel Plugin React Persist
Automatically useCallback() & useMemo(); memoize inline functions
Stars: ✭ 91 (-35.92%)
Mutual labels:  babel, babel-plugin
Babel Plugin Prismjs
A babel plugin to use PrismJS with standard bundlers.
Stars: ✭ 114 (-19.72%)
Mutual labels:  babel, babel-plugin

babel-plugin-transform-typescript-metadata

Travis (.com) Codecov npm

Babel plugin to emit decorator metadata like typescript compiler

Motivation

TypeScript Decorators allows advanced reflection patterns when combined with Reflect.metadata output.

Current @babel/preset-typescript implementation however just strips all types and does not emit the relative Metadata in the output code.

Since this kind of information is used extensively in libraries like Nest and TypeORM to implement advanced features like Dependency Injection, I've thought it would be awesome to be able to provide the same functionality that TypeScript compiler experimentalDecorators and emitDecoratorMetadata flags provide.

This means that code like:

import { Injectable, Inject } from 'some-di-library'; // Just an example
import { MyService } from './MyService';
import { Configuration } from './Configuration';

@Injectable()
class AnotherService {
  @Inject()
  config: Configuration;

  constructor(private service: MyService) {}
}

will be interpreted like:

import { MyService } from './MyService';
import { Configuration } from './Configuration';

@Injectable()
@Reflect.metadata('design:paramtypes', [MyService])
class AnotherService {
  @Inject()
  @Reflect.metadata('design:type', Configuration)
  config: Configuration;

  constructor(private service: MyService) {}
}

Parameter decorators

Since decorators in typescript supports also Parameters, this plugin also provides support for them, enabling the following syntax:

@Injectable()
class Some {
  constructor(@Inject() private: SomeService);
}

This will be roughly translated to:

// ...
Inject()(Some.prototype, undefined, 0);

Installation

With npm:

npm install --dev --save babel-plugin-transform-typescript-metadata

or with Yarn:

yarn add --dev babel-plugin-transform-typescript-metadata

Usage

With .babelrc:

Note: should be placed before @babel/plugin-proposal-decorators.

{
  "plugins": [
    "babel-plugin-transform-typescript-metadata",
    ["@babel/plugin-proposal-decorators", { "legacy": true }],
    ["@babel/plugin-proposal-class-properties", { "loose": true }],
  ],
  "presets": [
    "@babel/preset-typescript"
  ]
}

Usage with InversifyJS

If you are using normal dependency injection letting Inversify create your instances, you should be fine with all kind of decorators.

Instead, if you are using property injection, when the container does not create the instances, you would likely encounter errors since babel decorators are not exactly the same as TypeScript.

You can fix it by enhancing property decorators with the following function:

import getDecorators from 'inversify-inject-decorators';
// setup the container...
let { lazyInject: originalLazyInject } = getDecorators(container);

// Additional function to make properties decorators compatible with babel.
function fixPropertyDecorator<T extends Function>(decorator: T): T {
  return ((...args: any[]) => (
    target: any,
    propertyName: any,
    ...decoratorArgs: any[]
  ) => {
    decorator(...args)(target, propertyName, ...decoratorArgs);
    return Object.getOwnPropertyDescriptor(target, propertyName);
  }) as any;
}

export const lazyInject = fixPropertyDecorator(originalLazyInject);

Current Pitfalls

  • If you are using webpack and it complains about missing exports due to types not being removed, you can switch from import { MyType } from ... to import type { MyType } from .... See #46 for details and examples.

  • We cannot know if type annotations are just types (i.e. IMyInterface) or concrete values (like classes, etc.). In order to resolve this, we emit the following: typeof Type === 'undefined' ? Object : Type. The code has the advantage of not throwing. If you know a better way to do this, let me know!

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].