Расширение интерфейса TypeScript из JavaScript: ошибка типа: класс расширяет неопределенное значение, не является функцией или нулем

#javascript #typescript

#javascript #typescript

Вопрос:

У меня есть интерфейс TypeScript, подобный этому:

 export interface Foo {
  bar: string
}
  

Это приведет к компиляции в пустой .js файл.
Поэтому при использовании интерфейса TypeScript в узловом модуле ES6 я получаю эту ошибку:

TypeError: Class extends value undefined is not a function or null

Обходным путем будет создание класса

 export class BaseFoo {
  bar: string
}
  

Теперь я могу использовать BaseFoo из ES6 без получения вышеупомянутой ошибки.
Таким образом, невозможно просто иметь интерфейсы в TypeScript с взаимодействием ES6 или есть более элегантный способ, чем наличие Base* классов (которые в конечном итоге не являются базовыми классами) здесь?

Обновить: Я понимаю различные концепции, лежащие в основе интерфейсов и базовых классов, но мои вопросы касаются наилучшей практики, как создать библиотеку в TypeScript, которая использует интерфейсы, и как построить ее таким образом, чтобы обычный ES6 (у которого нет интерфейсов) также мог использовать эту библиотеку.

Комментарии:

1. Что вы имеете в виду, используя интерфейс? Typescript не позволит вам использовать интерфейс, поскольку интерфейсы — это просто типы, а типы стираются. Вы используете интерфейсы для проверки типа значений в typescript, во время выполнения они бесполезны.

2. Класс реализует интерфейс, он не может его расширять.

3. @TitianCernicova-Dragomir Я обновил вопрос.

4. @AlexanderZeitler потребителю js просто наплевать на интерфейсы, код все еще можно использовать, где интерфейс должен быть передан, они могут просто передать объектный литерал, который удовлетворяет интерфейсу (конечно, без проверки) или классу, который они создают. Вы также можете создавать классы для интерфейсов, но я не думаю, что для этого есть причина, если у вас нет другого требования..

5. Если я не создаю class в TS, я получаю вышеупомянутую ошибку. Я хочу убедиться, что сигнатура свойства interface из TS также будет доступна. Итак, мое текущее понимание таково, что я могу использовать interface в TS как есть, но для взаимодействия с JS мне нужно создать, class которое можно extend редактировать в обычном JS, не приводя к ошибке выше. Чтобы действовать более interface похоже, я также мог бы добавить NotImplementedError s в класс, который я extend создаю.

Ответ №1:

Я думаю, вы неправильно понимаете, как правильно использовать интерфейс. Интерфейсы не являются «базовыми» объектами, они просто определяют, как должен выглядеть объект.

В typescript интерфейс часто используется как тип для объекта, но в целом его можно использовать и для определения того, как должен «выглядеть» класс.

Например:

 interface Foo {
  bar: string;
  baz: number;
  bang(): void;
}
  

В этом случае любой объект / класс, который implements Foo должен будет иметь эти три вещи.

IE:

 class FooImplemented implements Foo {
  bar = 'Hello World';
  baz = 42;

  bang() {
    print(this.bar);
  }
}
  

Если я не определю bar, baz и / или bang; typescript выдаст ошибку во время компиляции, что я неправильно реализую Foo интерфейс в FooImplemented классе.

Подводя итог, интерфейс сообщает компилятору, как что-то должно выглядеть. И интерфейс может расширять другой интерфейс. Однако класс не может расширить интерфейс, но он может его реализовать. (Или несколькими)

Ознакомьтесь с документами по интерфейсам на веб-сайте typescripts.

Комментарии:

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

2. @AlexanderZeitler ошибка предполагает, что вы используете extends вместо implements ?

3. @Evert implements не существует в обычном JS, вот почему я использую extends , и именно по этой причине я ищу обходной путь / наилучшую практику для решения всей этой проблемы.

4. @AlexanderZeitler ах, теперь я понимаю. Тогда эквивалент, не являющийся typescript, на самом деле не реализует / расширяет все это. В этом не было бы смысла, потому что все это происходило бы во время выполнения, а typescript вообще ничего не применяет во время выполнения.

Ответ №2:

Возможно, вы захотите использовать эту аннотацию @implements jsdoc:

 /** @implements {Print} */
class TextBook {
  print() {
    // TODO
  }
}