LoginSignup
25
23

More than 5 years have passed since last update.

typescriptはクラスをインターフェイスとして使えるらしい

Last updated at Posted at 2016-05-04

typescriptはクラスをインターフェイスとして使えるらしい

はじめに

あるオブジェクトに機能を追加したい場合に、委譲するコードを書くことがある。
それそのものとしてのインターフェイスが欲しい場合にはクラスをインターフェイスとして使える

例えば以下の様なオブジェクトがあるとする。

class Container {
  constructor(public value: number) {}

  display() {
    return `node: ${this.value}`;
  }
}

console.log(new Container(10).display());
// "node: 10"

この Container オブジェクトに対して何らかの機能を追加したオブジェクトを作りたい。継承ではなく委譲を使った場合のコードについて考えてみる。

まじめにインターフェイスを定義する

通常は以下の様にインターフェイスを書く(implements を明示的に指定する必要はないかもしれない)

interface IContainer {
  value: number;
  display(): string;
}

class PositiveContainer implements IContainer {
  constructor(public c: Container) {}

  get value(): number {
    return this.c.value;
  }

  set value(value: number) {
    if (value < 0) {
      throw new Error(`${value} is not positive.`);
    }
    this.c.value = value;
  }

  display() {
    return this.c.display();
  }
}

明示的にimplementsをしたい理由として、委譲元のオブジェクトに機能が追加された時にコンパイルの時点でそれをみつけて欲しいというのがある。

まじめにインターフェイスを定義した場合には、元のオブジェクトと定義したインターフェイスの同期がとれていないとコンパイルエラーにはならない。

クラスをインターフェイスとして使う

implements の後にクラスを指定した場合に、指定したクラスがインターフェイスとして扱われる。
デコレーター的なオブジェクトを作ろうとした時には便利なような気がしている。
(もっとも、元のオブジェクトと異なるインターフェイスを定義したいという場合もあるのでそのような場合は真面目にインターフェイスを定義するべき)

// IContainerを定義せずに`implements Container` と書いている
class PositiveContainer2 implements Container {
  constructor(public c: Container) {}

  get value(): number {
    return this.c.value;
  }

  set value(value: number) {
    if (value < 0) {
      throw new Error(`${value} is not positive.`);
    }
    this.c.value = value;
  }

  display() {
    return this.c.display();
  }
}

参考

typescriptのhandbookにクラスをインターフェイスとして使う例としてmixinを行う例があった

Wrote by PileMd

25
23
1

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
25
23