Чи можете ви вказати декілька обмежень типу для загальних типів 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
Типи об'єднань - чудовий спосіб досягти цього, оскільки вам не потрібно створювати інтерфейс з єдиною метою обмеження. Їх не існувало ще в 2013 році - але це точно, як я б рекомендував зробити це зараз.
Фентон,

5
Ця відповідь неправильна. Типи об'єднань взагалі не мають тієї самої семантики, як розширення двох різних типів.
AlexG

3
@AlexG Звичайно, це не те саме, що розширити два типи, але те саме, що реалізувати два інтерфейси.
STO

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

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

34

Для цього можна було б використати суперінтерфейс (який також відповідає на питання "чому ви дозволяєте інтерфейсу успадковуватись від класу").

interface ISuperInterface extends MyClass, OtherClass {

}

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

12
Це правильне рішення. Розширення інтерфейсу з двох класів є якось страшним, однак - якщо обидва оголошують приватних членів, інтерфейс неможливо виконати
Райан Кавано

1

Посилання на коментар щодо інтерфейсу, що походить від класу ... що в назві?

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

Оголошення інтерфейсу вводять лише іменовані типи, тоді як оголошення класів вводять іменовані типи та функції конструктора, які створюють екземпляри реалізацій цих іменованих типів. Названі типи, запроваджені оголошеннями класів та інтерфейсів, мають лише незначні відмінності (класи не можуть оголошувати необов'язкові члени, а інтерфейси не можуть оголошувати приватні члени) і в більшості контекстів взаємозамінні. Зокрема, декларації класів лише з загальнодоступними членами вводять іменовані типи, які функціонують точно так само, як ті, що створені деклараціями інтерфейсу.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.