web-dev-qa-db-fra.com

Comment créer un objet basé sur une définition de fichier d'interface dans TypeScript?

J'ai défini une interface comme celle-ci:

interface IModal {
    content: string;
    form: string;
    href: string;
    $form: JQuery;
    $message: JQuery;
    $modal: JQuery;
    $submits: JQuery;
 }

Je définis une variable comme celle-ci:

var modal: IModal;

Cependant, lorsque j'essaie de définir la propriété de modal, cela me donne un message disant que

"cannot set property content of undefined"

Puis-je utiliser une interface pour décrire mon objet modal et si oui, comment dois-je le créer?

243
user1679941

Si vous créez la variable "modal" ailleurs et que vous voulez dire à TypeScript que tout sera fait, vous utiliserez:

declare const modal: IModal;

Si vous souhaitez créer une variable qui sera réellement une instance de IModal dans TypeScript, vous devrez la définir complètement.

const modal: IModal = {
    content: '',
    form: '',
    href: '',
    $form: null,
    $message: null,
    $modal: null,
    $submits: null
};

Ou bien, avec une assertion de type, mais vous perdrez la sécurité de type car vous allez maintenant devenir indéfini dans des endroits inattendus, et éventuellement des erreurs d'exécution, en accédant à modal.content et ainsi de suite (propriétés stipulées dans le contrat). .

const modal = {} as IModal;

Exemple de classe

class Modal implements IModal {
    content: string;
    form: string;
    href: string;
    $form: JQuery;
    $message: JQuery;
    $modal: JQuery;
    $submits: JQuery;
}

const modal = new Modal();

Vous pensez peut-être que "c'est vraiment une duplication de l'interface" - et vous avez raison. Si la classe Modal est la seule implémentation de l'interface IModal, vous voudrez peut-être la supprimer complètement et utiliser ...

const modal: Modal = new Modal();

Plutôt que

const modal: IModal = new Modal();
326
Fenton

Si vous voulez un objet vide d'une interface, vous pouvez simplement faire:

var modal = <IModal>{};

L'avantage d'utiliser des interfaces au lieu de classes pour structurer des données est que si vous n'avez aucune méthode sur la classe, celle-ci sera affichée dans JS compilé en tant que méthode vide. Exemple:

class TestClass {
    a: number;
    b: string;
    c: boolean;
}

compile en

var TestClass = (function () {
    function TestClass() {
    }
    return TestClass;
})();

qui n'a aucune valeur. Les interfaces, en revanche, n'apparaissent pas du tout dans JS, tout en offrant les avantages de la structuration des données et de la vérification de type.

168
user3180970

Si vous utilisez React, l'analyseur s'interroge sur la syntaxe de conversion traditionnelle. Une alternative a donc été introduite pour une utilisation dans les fichiers . Tsx .

let a = {} as MyInterface;

https://www.typescriptlang.org/docs/handbook/jsx.html

37
geg

Je pense que vous avez fondamentalement cinq options différentes pour le faire. Choisir parmi eux pourrait être facile en fonction de l'objectif que vous souhaitez atteindre.

La meilleure façon dans la plupart des cas d’utiliser une classe et de l’instancier , car vous utilisez TypeScript pour appliquer la vérification de type.

interface IModal {
    content: string;
    form: string;
    //...

    //Extra
    foo: (bar: string): void;
}

class Modal implements IModal {
    content: string;
    form: string;

    foo(param: string): void {
    }
}

Même si d'autres méthodes offrent des moyens plus simples de créer un objet à partir d'une interface, vous devez envisager de séparer votre interface , si vous utilisez votre objet à des fins différentes. , et cela ne provoque pas de sur-ségrégation d'interface:

interface IBehaviour {
    //Extra
    foo(param: string): void;
}

interface IModal extends IBehaviour{
    content: string;
    form: string;
    //...
}

D'un autre côté, par exemple lors du test de code de votre unité (si vous n'appliquez pas souvent la séparation des problèmes), vous pourrez peut-être accepter les inconvénients pour des raisons de productivité. Vous pouvez appliquer d'autres méthodes pour créer des simulacres, principalement pour les interfaces tierces * .d.ts. Et il pourrait être pénible de toujours implémenter des objets anonymes complets pour chaque énorme interface.

Sur ce chemin, votre première option consiste à créer un objet vide :

 var modal = <IModal>{};

Deuxièmement, pour comprendre pleinement la partie obligatoire de votre interface . Cela peut être utile si vous appelez des bibliothèques JavaScript tierces, mais je pense que vous devriez plutôt créer une classe, comme auparavant:

var modal: IModal = {
    content: '',
    form: '',
    //...

    foo: (param: string): void => {
    }
};

Troisièmement, vous pouvez créer une partie de votre interface et créer un objet anonyme , mais de cette façon, vous êtes responsable de l'exécution du contrat

var modal: IModal = <any>{
    foo: (param: string): void => {

    }
};

Résumant ma réponse, même si les interfaces sont facultatives, parce qu'elles ne sont pas transpilées en code JavaScript, TypeScript est là pour fournir un nouveau niveau d'abstraction, s'il est utilisé à bon escient et de manière cohérente. Je pense que vous ne devriez pas, car dans la plupart des cas, vous pouvez les écarter de votre propre code.

17
Ursegor

Tu peux faire

var modal = {} as IModal 

Depuis que je n'ai pas trouvé une réponse égale dans le haut et ma réponse est différente. Je fais:

modal: IModal = <IModal>{}
8
Zokor

En utilisant votre interface, vous pouvez faire

class Modal() {
  constructor(public iModal: IModal) {
   //You now have access to all your interface variables using this.iModal object,
   //you don't need to define the properties at all, constructor does it for you.
  }
}
1
Byrd