web-dev-qa-db-fra.com

Est-il possible d'utiliser des getters / setters dans la définition d'interface?

Pour le moment, TypeScript n'autorise pas l'utilisation de méthodes get/set (accesseurs) dans les interfaces. Par exemple:

interface I {
      get name():string;
}

class C implements I {
      get name():string {
          return null;
      } 
}

de plus, TypeScript n'autorise pas l'utilisation de Array Function Expression dans les méthodes de classe: par exemple:

class C {
    private _name:string;

    get name():string => this._name;
}

Existe-t-il un autre moyen d'utiliser un getter et un setter dans une définition d'interface?

71
Ivan Popov

Vous pouvez spécifier la propriété sur l'interface, mais vous ne pouvez pas imposer l'utilisation de getters et de setters, comme ceci:

interface IExample {
    Name: string;
}

class Example implements IExample {
    private _name: string = "Bob";

    public get Name() {
        return this._name;
    }

    public set Name(value) {
        this._name = value;
    }
}

var example = new Example();
alert(example.Name);

Dans cet exemple, l'interface ne force pas la classe à utiliser des accesseurs (getters), j'aurais pu utiliser une propriété (exemple ci-dessous), mais l'interface est supposée masquer ces détails d'implémentation, car il s'agit d'une promesse faite au code appelant. à propos de ce qu'il peut appeler.

interface IExample {
    Name: string;
}

class Example implements IExample {
    // this satisfies the interface just the same
    public Name: string = "Bob";
}

var example = new Example();
alert(example.Name);

Et enfin, => n'est pas autorisé pour les méthodes de classe - vous pourriez lancer une discussion sur Codeplex si vous pensez que le cas d'utilisation est enflammé. Voici un exemple:

class Test {
    // Yes
    getName = () => 'Steve';

    // No
    getName() => 'Steve';

    // No
    get name() => 'Steve';
}
100
Fenton

Pour compléter les autres réponses, si vous souhaitez définir un get value sur une interface, vous pouvez utiliser readonly:

interface Foo {
  readonly value: number;
}

let foo: Foo = { value: 10 };

foo.value = 20; //error

class Bar implements Foo {
  get value() {
    return 10;
  }
}

mais pour autant que je sache et comme d'autres l'ont mentionné, il n'y a actuellement aucun moyen de définir une propriété set-only dans l'interface. Vous pouvez toutefois déplacer la limitation vers une erreur d'exécution (utile uniquement pendant le cycle de développement):

interface Foo {
  /* Set Only! */
  value: number;
}

class Bar implements Foo {
  _value:number;
  set value(value: number) {
    this._value = value;
  }
  get value() {
    throw Error("Not Supported Exception");
  }
}

Pratique non recommandée; mais une option.

27
Meirion Hughes

Tout d’abord, TypeScript ne prend en charge que la syntaxe get et set lorsqu’on cible Ecmascript 5. Pour ce faire, vous devez appeler le compilateur avec

tsc --target ES5

Les interfaces ne prennent pas en charge les getters et les setters. Pour que votre code soit compilé, vous devez le changer en

interface I { 
    getName():string;
}

class C implements I { 
    getName():string {
          return null;
    }   
}

Ce que TypeScript prend en charge est une syntaxe spéciale pour les champs des constructeurs. Dans votre cas, vous pourriez avoir

interface I {
    getName():string;
}

class C implements I {
    constructor(public name: string) {
    }
    getName():string {
        return name;
    }
}

Notez que la classe C ne spécifie pas le champ name. Il est en fait déclaré en utilisant du sucre syntaxique public name: string dans le constructeur.

Comme le souligne Sohnee, l'interface est censée masquer tous les détails de la mise en œuvre. Dans mon exemple, j'ai choisi l'interface pour exiger une méthode getter de style Java. Cependant, vous pouvez également utiliser une propriété, puis laisser la classe décider de la mise en œuvre de l'interface.

2
Valentin

Utilisation de TypeScript 3.4:

interface IPart {
    getQuantity(): number;
}

class Part implements IPart {
    private quantity: number;
    constructor(quantity: number) {
        this.quantity = quantity;
    }
    public getQuantity = (): number => {
        return this.quantity;
    };
}

let part = new Part(42);

// When used in TypeScript, quantity is not accessible.
// However, when compiled to javascript it will log '42'.
console.log(part.quantity);

// Logs '42'.
console.log(part.getQuantity());

Voir l'exemple sur TypeScript Playground .

0
Jack