LoginSignup
7
6

More than 5 years have passed since last update.

es7.decorator でプロパティ validation やるとこんな感じなのだろうか

Last updated at Posted at 2015-05-21

仕様: https://github.com/wycats/javascript-decorators

プロパティ自体に decorator は付か無いので、しかたなく setter を作ったけど、なんかうまくできないだろうか。
(この使い方自体が筋悪な気もするが、 decorator でやりたいのってこういうのな気がする。)

// $ babel-node --optional es7.decorators index.js
class Assert {
  private(target, name, descriptor) {
    let value;
    descriptor.set = (val) => {
      value = val;
    }
    descriptor.get = () => {
      return value;
    }
  }

  required(target, name, descriptor) {
    let original = descriptor.set;
    descriptor.set = (val) => {
      console.assert(val !== undefined, `${name} is required`);
      original(val);
    }
  }

  validate(target, name, descriptor) {
    let original = descriptor.set;
    descriptor.set = (val) => {
      console.assert(val.method !== undefined, `${name}.val is required`);

      let method_list = ['get', 'post', 'put', 'delete'];
      console.assert(method_list.indexOf(val.method) > -1, `${name}.val should be one of ${method_list} but ${val.method}`);
      original(val);
    }
  }
}

var assert = new Assert();

class Fetcher {

  @assert.required
  @assert.private
  set url(val) {}

  @assert.validate
  @assert.required
  @assert.private
  set option(val) {}

  constructor(url, option) {
    this.url = url;
    this.option = option;
  }
}

var fetcher = new Fetcher('http://example.com', { method: 'get' });
console.log(fetcher);         // {}
console.log(fetcher.url);     // http://example.com
console.log(fetcher.options); // { method: 'get' }

追記

関数の引数を先に奪ってバリデート

class Fetcher {

  @assert.required
  @assert.private
  set url(val) {}

  @assert.validate
  @assert.required
  @assert.private
  set option(val) {}

  constructor(url, option) {
    this.url = url;
    this.option = option;
  }
}

var fetcher = new Fetcher('http://example.com', { method: 'get' });
console.log(fetcher);         // {}
console.log(fetcher.url);     // http://example.com
console.log(fetcher.options); // { method: 'get' }

汎用の関数 wrapper を作るアノテーションを別途用意。

class Fetcher {

  @assert.required
  @assert.private
  set url(val) {}

  @assert.validate
  @assert.required
  @assert.private
  set option(val) {}

  constructor(url, option) {
    this.url = url;
    this.option = option;
  }
}

var fetcher = new Fetcher('http://example.com', { method: 'get' });
console.log(fetcher);         // {}
console.log(fetcher.url);     // http://example.com
console.log(fetcher.options); // { method: 'get' }
7
6
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
7
6