web-dev-qa-db-ja.com

TypeScriptクラスと同じ名前のインターフェース間の関係

TypeScriptクラスと同じ名前のインターフェイス間の特殊な関係の明確なドキュメントまたは説明を見つけるのに少し問題があります。

  • クラスと同じ名前のインターフェースの意味は何ですか?
  • インターフェースと名前を共有するクラスがそのインターフェースを自動的に実装するのはなぜですか?
  • クラスとインターフェースの名前が同じである場合、コンパイラーは読み取り専用インターフェースフィールドのゲッター実装について文句を言うのに、名前が異なる場合は実装を受け入れますか?
  • これらの質問に対処する正規のドキュメントはありますか?

コード:

// Co-named interface and class doesn't like readonly property implementation:

interface Foo {
  readonly x: number; // Error: Duplicate identifier 'x'
  y: number;
}

class Foo {
  get x(): number { // Error: Duplicate identifier 'x'
    return 0;
  }

  y = 1;
}

// Same as above, but different class name + explicit `implements`

class Bar implements Foo {
  get x(): number { // No error!
    return 0;
  }

  y = 1;
}

// Duplicating the first example, but explicitly implementing the co-named interface:

interface Baz {
  readonly x: number; // Error: Duplicate identifier 'x'
  y: number;
}

class Baz implements Baz {
  get x(): number { // Error: Duplicate identifier 'x'
    return 0;
  }

  y = 1;
}
32
Nathan Ridley

モジュール内の同じ名前のインターフェース マージされます

_interface Foo {
    x: number;
}

interface Foo {
    y: string;
}

let g = {} as Foo;
g.x; // OK
g.y; // OK
_

クラス宣言は コンストラクタ関数と型宣言の両方 を作成します。これは基本的に、すべてのクラスをインターフェイスとして使用できることを意味します。

_class Bar {
    y: number;
}

interface IBaz extends Bar { } // includes y: number

class CBaz implements Bar {
    y: number = 5;
}
_

したがって、同じ名前のクラスとインターフェイスを持つことは、同じ名前の2つのインターフェイスを持つことと同等であり、インターフェイスの両方のインスタンスが異なる型の同じメンバーを再宣言すると、マージの競合が発生します。

奇妙なことに、TypeScriptはこれを可能にします。

_export interface Foo {
    readonly x: number;
}

export class Foo {
    readonly x: number = 3;
}
_

しかし、これらは両方とも_readonly x: number_として生成されますが、get x() { return 3; }を許可しません。したがって、型チェッカーは、意味的に同じであるにもかかわらず、マージ中にそれらを異なるものと見なすことしか想像できません(これはこれが、インターフェースを拡張し、readonlyプロパティをゲッター関数として指定できる理由です)。

20
y2bd