5

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

14

Я определил интерфейс следующим образом:

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"

Правильно ли использовать интерфейс для описания моего объекта модального окна? И как мне нужно его создать, чтобы избежать этой ошибки?

5 ответ(ов)

7

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

declare const modal: IModal;

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

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

Или вы можете "сказать" TypeScript, что это так, с помощью утверждения типа, но в этом случае вы потеряете безопасность типов, что может привести к неожиданному получению undefined в тех местах, где вы ожидаете доступ к свойствам 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();
2

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

var modal = <IModal>{};

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

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

При компиляции это преобразуется в:

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

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

1

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

let a = {} as MyInterface;

вы можете использовать следующий синтаксис:

let a = {} as MyInterface;

Этот способ позволяет избежать проблем с парсингом, связанные с JSX. Более подробную информацию можно найти в документации TypeScript.

0

На StackOverflow можно ответить на вопрос следующим образом:

Существует 5 способов использования интерфейса IStudent.

interface IStudent {
    Id: number;
    name: string;
}

Метод 1. Все поля должны быть заполнены данными.

const obj1: IStudent = { Id: 1, name: 'Naveed' };

Метод 2. Мой любимый способ.

const obj2 = { name: 'Naveed' } as IStudent;

Метод 3.

const obj3 = <IStudent>{ name: 'Naveed' };

Метод 4. Используйте Partial интерфейс, если не все поля обязательны.

const obj4: Partial<IStudent> = { name: 'Naveed' };

Метод 5. Используйте знак ? для полей интерфейса, если не все поля обязательны.

interface IStudent {
    Id?: number; // делаем Id необязательным
    name: string;
}

const obj5: IStudent = { name: 'Naveed' };

Надеюсь, это поможет! Если у вас есть дополнительные вопросы, не стесняйтесь спрашивать.

0

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

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

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

    //Дополнительное
    foo: (bar: string) => void;
}

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

    foo(param: string): void {
        // Реализация метода
    }
}

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

interface IBehaviour {
    //Дополнительное
    foo(param: string): void;
}

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

С другой стороны, например, во время юнит-тестирования вашего кода (если вы не часто применяете принцип разделения обязанностей) вы можете принять недостатки ради повышения продуктивности. Вы можете использовать другие методы для создания моков, обычно для больших интерфейсов третьих сторон *.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 предоставляет новый уровень абстракции, если его использовать мудро и последовательно. Я думаю, что просто потому, что вы можете игнорировать их в большинстве случаев, вам не следует этого делать.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь