Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/leonardfactory/babel-plugin-transform-typescript-metadata
Babel plugin to emit decorator metadata like typescript compiler
https://github.com/leonardfactory/babel-plugin-transform-typescript-metadata
babel babel-plugin babel-typescript decorators reflect-metadata typescript
Last synced: 3 months ago
JSON representation
Babel plugin to emit decorator metadata like typescript compiler
- Host: GitHub
- URL: https://github.com/leonardfactory/babel-plugin-transform-typescript-metadata
- Owner: leonardfactory
- License: mit
- Created: 2019-03-24T11:32:22.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2023-09-13T15:33:42.000Z (about 1 year ago)
- Last Synced: 2024-07-29T08:04:38.110Z (3 months ago)
- Topics: babel, babel-plugin, babel-typescript, decorators, reflect-metadata, typescript
- Language: JavaScript
- Size: 1.04 MB
- Stars: 217
- Watchers: 3
- Forks: 17
- Open Issues: 13
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- awesome-list - babel-plugin-transform-typescript-metadata
README
# babel-plugin-transform-typescript-metadata
![GitHub Workflow Build Status](https://img.shields.io/github/workflow/status/leonardfactory/babel-plugin-transform-typescript-metadata/CI/master)
[![Codecov](https://img.shields.io/codecov/c/github/leonardfactory/babel-plugin-transform-typescript-metadata.svg)](https://codecov.io/gh/leonardfactory/babel-plugin-transform-typescript-metadata)
[![npm](https://img.shields.io/npm/v/babel-plugin-transform-typescript-metadata.svg?style=popout)](https://www.npmjs.com/package/babel-plugin-transform-typescript-metadata)Babel plugin to emit decorator metadata like typescript compiler
## Motivation
TypeScript _Decorators_ allows advanced reflection patterns when combined
with [`Reflect.metadata`](https://rbuckton.github.io/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](https://docs.nestjs.com/providers) and [TypeORM](https://typeorm.io/#/)
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](https://www.typescriptlang.org/docs/handbook/decorators.html) provide.This means that code like:
```ts
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:
```ts
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:```ts
@Injectable()
class Some {
constructor(@Inject() private: SomeService);
}
```This will be roughly translated to:
```js
// ...
Inject()(Some.prototype, undefined, 0);
```## Installation
With npm:
```sh
npm install --dev --save babel-plugin-transform-typescript-metadata
```or with Yarn:
```sh
yarn add --dev babel-plugin-transform-typescript-metadata
```## Usage
With `.babelrc`:
> **Note:** should be placed **before** `@babel/plugin-proposal-decorators`.
```js
{
"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](http://inversify.io)
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](https://github.com/inversify/InversifyJS/blob/master/wiki/property_injection.md#when-we-cannot-use-inversifyjs-to-create-an-instance-of-a-class),
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:
```ts
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(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](https://github.com/leonardfactory/babel-plugin-transform-typescript-metadata/issues/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!