Как я могу создать объект на основе определения файла интерфейса в TypeScript?

195

Я определил такой интерфейс:

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

Я определяю такую ​​переменную:

var modal: IModal;

Однако, когда я пытаюсь установить свойство modal, он дает мне сообщение о том, что

"cannot set property content of undefined"

Может кто-нибудь мне помочь? Можно ли использовать интерфейс для описания моего модального объекта, и если да, то как его создать?

Теги:

7 ответов

263
Лучший ответ

Если вы создаете "модальную" переменную в другом месте и хотите сообщить TypeScript, что все это будет сделано, вы должны использовать:

declare const modal: IModal;

Если вы хотите создать переменную, которая на самом деле будет экземпляром IModal в TypeScript, вам нужно будет определить ее полностью.

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

Или ложь с утверждением типа, но вы потеряете безопасность типов, поскольку теперь вы будете получать неопределенные значения в неожиданных местах и, возможно, во время выполнения при доступе к modal.content и т.д. (Свойства, которые, согласно контракту, будут там).

const modal = {} as IModal;

Пример класса

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

const modal = new Modal();

Вы можете подумать "эй, что на самом деле дублирование интерфейса" - и вы правы. Если класс Modal является единственной реализацией интерфейса IModal, вы можете вообще удалить интерфейс и использовать...

const modal: Modal = new Modal();

Скорее, чем

const modal: IModal = new Modal();
  • 1
    Благодарю. Я надеялся избавиться от необходимости определять все модальное содержимое изначально. Было бы проще, если бы вместо интерфейса я определил Modal как класс со свойствами, а затем использовал new и конструктор для установки всех начальных значений?
  • 1
    Да, вы можете определить класс, и тогда вам придется создавать новые экземпляры только тогда, когда они вам нужны. Вам нужен пример?
Показать ещё 8 комментариев
143

Если вам нужен пустой объект интерфейса, вы можете сделать только:

var modal = <IModal>{};

Преимущество использования интерфейсов вместо классов для структурирования данных заключается в том, что, если у вас нет каких-либо методов в классе, он будет отображаться в скомпилированном JS как пустой метод. Пример:

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

компилируется в

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

который не имеет значения. С другой стороны, интерфейсы вообще не отображаются в JS, сохраняя при этом преимущества структурирования данных и проверки типов.

  • 1
    `Добавить к вышеупомянутому комментарию. Чтобы вызвать функцию "updateModal (IModal modalInstance) {}", вы можете создать встроенный экземпляр интерфейса 'IModal', например, так: // здесь есть некоторый код, где доступны функция updateModal и IModal: updateModal (<IModal> {// эта строка создает содержимое экземпляра: '', form: '', href: '', $ form: null, $ message: null, $ modal: null, $ submits: null}); // завершаем ваш код
  • 0
    используя var modal= <abc>{} мы только что присвоили модальный тип abc пустого объекта, но где мы объявили тип модального? Я использую TypeScript6.
32

Если вы используете React, синтаксический анализатор будет подавлять традиционный синтаксис, поэтому была использована альтернатива для использования в файлах .tsx.

let a = {} as MyInterface;

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

16

Я думаю, что у вас есть в основном пять различных опций. Выбор среди них может быть легким в зависимости от цели, которую вы хотели бы достичь.

Лучший способ в большинстве случаев использовать использовать класс и создавать его, потому что вы используете TypeScript для применения проверки типов.

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

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

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

    foo(param: string): void {
    }
}

Даже если другие методы предлагают более простые способы создания объекта из интерфейса, вы должны рассмотреть раздел разделение вашего интерфейса, если вы используете свой объект по разным вопросам, и это не вызывает -сегрегация:

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

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

С другой стороны, например, во время модульного тестирования вашего кода (если вы не можете часто применять разделение проблем), вы можете принять недостатки ради производительности. Вы можете применять другие методы для создания mocks в основном для больших сторонних интерфейсов *.d.ts. И может быть больно всегда реализовывать полные анонимные объекты для каждого огромного интерфейса.

На этом пути ваш первый вариант - создать пустой объект:

 var modal = <IModal>{};

Во-вторых, полностью реализовать обязательную часть вашего интерфейса. Это может быть полезно, если вы вызываете сторонние библиотеки JavaScript, но я думаю, что вы должны создать класс, а не раньше:

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

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

В-третьих, вы можете создать только часть вашего интерфейса и создать анонимный объект , но таким образом вы несете ответственность за выполнение контракта

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

    }
};

Подводя итог моему ответу, даже если интерфейсы являются необязательными, потому что они не передаются в код JavaScript, TypeScript должен предоставить новый уровень абстракции, если использовать его мудро и последовательно. Я думаю, только потому, что вы можете уволить их в большинстве случаев из вашего собственного кода, вы не должны.

13

Вы можете сделать

var modal = {} as IModal 
5

Так как я не нашел равного ответа в топе, и мой ответ другой. Я делаю:

modal: IModal = <IModal>{}
1

Используя ваш интерфейс вы можете сделать

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.
  }
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню