web-dev-qa-db-fra.com

Relation entre une classe TypeScript et une interface du même nom

J'ai un peu de mal à trouver une documentation ou une explication claire pour la relation apparemment spéciale entre une classe TypeScript et une interface du même nom.

  • Quelle est la signification d'une interface avec le même nom qu'une classe?
  • Pourquoi une classe qui partage son nom avec une interface implémente-t-elle automatiquement cette interface?
  • Pourquoi le compilateur se plaint-il de mon implémentation getter d'un champ d'interface en lecture seule lorsque la classe et l'interface ont le même nom, mais acceptent l'implémentation si les noms sont différents?
  • Existe-t-il une documentation canonique traitant de ces questions?

Code:

// 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

Interfaces du même nom dans un module seront fusionnées :

interface Foo {
    x: number;
}

interface Foo {
    y: string;
}

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

Une déclaration de classe crée à la fois une fonction constructeur et une déclaration de type , ce qui signifie essentiellement que toutes les classes peuvent être utilisées comme interfaces.

class Bar {
    y: number;
}

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

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

Par conséquent, avoir une classe et une interface avec le même nom équivaut à avoir deux interfaces avec le même nom, et vous obtiendrez des conflits de fusion si les deux instances de l'interface déclarent à nouveau les mêmes membres avec des types différents.

Curieusement, TypeScript permettra cela:

export interface Foo {
    readonly x: number;
}

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

mais cela n'autorisera pas get x() { return 3; } même si les deux génèrent comme readonly x: number, donc je peux seulement imaginer que le vérificateur de type les considère comme différents pendant la fusion même s'ils sont sémantiquement les mêmes ( c'est pourquoi vous pouvez étendre l'interface et spécifier la propriété en lecture seule en tant que fonction getter).

20
y2bd