6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Node.jsアドベントカレンダーの記事です。

JavaScript本体の仕様策定でなかなかステージ3にあがらないデコレータ
TypeScriptには--experimentalDecoratorsオプションが必要ですが、以前から実装されています。この場合にのみメタデータが扱えるようになっています。

メタデータのプリミティブな使い方を書いておきます。greetingメソッドにメタデータを付与します。それを実行時に取り出して表示しています。

import "reflect-metadata";
 
class A {
  @Reflect.metadata("metadata-key-dayo", "hello world")
  greeting() {
    const message = Reflect.getMetadata("metadata-key-dayo", this, "greeting");
    console.log(message);
  }
}

const a = new A();
a.method();
// hello world

どんな値でも入れられる便利な箱となっています。

--emitDecoratorMetadataオプションをつけると、TypeScriptは次のようなコードを生成します。

var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
__decorate([
    Reflect.metadata("metadata-key-dayo", "hello world"),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", void 0)
], A.prototype, "method", null);

このreflect-metadataパッケージを使ったコードです。細かいところを省くと、上記のサンプルのようなメタデータが自動で追加されます。それには"design:type"と、"design:parameters"と"design:returntype"というキーでもろもろの情報が付与されることがわかります。フィールドデコレータがついた場合は"design:type"だけで、クラスには特に追加のメタデータは付与されません。

最初のサンプルはメソッドの中で情報を取得しましたが、そのインスタンスメソッドの中でも外でも、同じようにこれらの情報にアクセスできます。

console.log("🐙", Reflect.getMetadata("design:type", a, "method"));
console.log("🐙", Reflect.getMetadata("design:paramtypes", a, "method"));
console.log("🐙", Reflect.getMetadata("design:returntype", a, "method"));

これらのメタデータは、あくまでも「なにかしらのメタデータが付与されたフィールド、クラス」に対する追加情報ですので、なにもデコレータが付いていなかった要素は型情報も取得できない点に注意です。

面白そうですよね?JSONからのシリアライズで型チェックをしながらクラスのフィールドに値を入れていくとかできそうですよね?

今までどういうものか調べようと思っていてずっと先延ばしにしていたのですが、ちょうどNode.jsアドベントカレンダーが空いていたので軽く調べて書いてみました。

詳しくはこちらに書いてあります。

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?