Можно ли указать несколько ограничений типа для Generics TypeScript


83

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

export interface IExample<T extends MyClass> {
    getById(id: number): T;
}

Можно ли указать несколько ограничений типа вместо одного?

Ответы:


87

Typescript не предлагает синтаксиса для множественного наследования универсальных типов. Однако вы можете добиться аналогичной семантики, используя типы Union и типы Intersection. В вашем случае вам нужен перекресток:

interface Example<T extends MyClass & OtherClass> {}

Для Союза обоих типов:

interface Example<T extends MyClass | OtherClass> {}

4
Типы Union - отличный способ добиться этого, поскольку вам не нужно создавать интерфейс с единственной целью ограничения. Их не было еще в 2013 году, но я бы рекомендовал сделать это сейчас именно так.
Fenton

5
Это неверный ответ. Типы Union вообще не имеют той же семантики, что и расширение двух разных типов.
AlexG

3
@AlexG Конечно, это не то же самое, что расширение двух типов, а то же самое, что реализация двух интерфейсов.
STO

6
Также имейте в виду, что Typescript также поддерживает типы пересечений. Поэтому <T extends MyInterfaceA & MyInterfaceB>требуется, чтобы тип реализовывал оба интерфейса.
Тайлер Клотье

2
Насколько я понимаю, семантика extends A|Bрасширяет A OR B, как extends A & Bрасширяет оба! так что, возможно, вам следует указать оба в своем ответе ....
Пипо

34

Обойти это можно, используя супер-интерфейс (который также отвечает на вопрос «почему вы позволяете интерфейсу наследовать от класса»).

interface ISuperInterface extends MyClass, OtherClass {

}

export interface IExample<T extends ISuperInterface> {
    getById(id: number): T;
}

12
Это правильное решение. Однако расширение интерфейса из двух классов немного пугает - если оба объявляют закрытые члены, интерфейс будет невыполнимым,
Райан Кавано,

1

Ссылка на комментарий об интерфейсе, производном от класса ... что в имени?

Я нашел это в разделе 3.5 спецификации 0.9.0:

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


Теперь реализованы необязательные члены класса: github.com/Microsoft/TypeScript/pull/8625
Стефан Рейн,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.