В чем разница между этими утверждениями (интерфейс против типа)?
interface X {
a: number
b: string
}
type X = {
a: number
b: string
};
В соответствии с TypeScript Спецификацией языка:
В отличие от декларации интерфейса, которая всегда вводит именованный тип объекта, объявление псевдонима типа может вводить имя для любого типа, включая типы примитива, объединения и пересечения.
Далее указывается:
Типы интерфейсов имеют много общего с типами псевдонимов для типа объекта литералов, но поскольку типы интерфейсов предлагают больше возможностей, они обычно предпочитают вводить псевдонимы. Например, тип интерфейса
interface Point { x: number; y: number; }
может быть записан как псевдоним типа
type Point = { x: number; y: number; };
Однако, это означает, что теряются следующие возможности:
- Интерфейс может быть назван в выражении extends или implement, но псевдоним типа для литерала типа объекта не может.
- Интерфейс может иметь несколько объединенных объявлений, но псевдоним типа для литерала типа объекта не может.
Текущие ответы и официальная документация устарели. А для новичков в TypeScript используемая терминология непонятна без примеров. Ниже приведен список актуальных различий.
И то, и другое можно использовать для описания формы объекта или сигнатуры функции. Но синтаксис отличается.
Интерфейс
interface Point {
x: number;
y: number;
}
interface SetPoint {
(x: number, y: number): void;
}
Введите псевдоним
type Point = {
x: number;
y: number;
};
type SetPoint = (x: number, y: number) => void;
В отличие от интерфейса, псевдоним типа может также использоваться для других типов, таких как примитивы, объединения и кортежи.
// primitive
type Name = string;
// object
type PartialPointX = { x: number; };
type PartialPointY = { y: number; };
// union
type PartialPoint = PartialPointX | PartialPointY;
// tuple
type Data = [number, string];
Оба могут быть расширены, но, опять же, синтаксис отличается. Кроме того, обратите внимание, что интерфейс и псевдоним типа не являются взаимоисключающими. Интерфейс может расширять псевдоним типа, и наоборот.
Интерфейс расширяет интерфейс
interface PartialPointX { x: number; }
interface Point extends PartialPointX { y: number; }
Тип псевдоним расширяет тип псевдоним
type PartialPointX = { x: number; };
type Point = PartialPointX & { y: number; };
Интерфейс расширяет псевдоним типа
type PartialPointX = { x: number; };
interface Point extends PartialPointX { y: number; }
Тип псевдоним расширяет интерфейс
interface PartialPointX { x: number; }
type Point = PartialPointX & { y: number; };
Класс может реализовывать интерфейс или псевдоним типа, оба одинаково точно. Обратите внимание, что класс и интерфейс считаются статическими чертежами. Поэтому они не могут реализовать/расширить псевдоним типа, который называет тип объединения.
interface Point {
x: number;
y: number;
}
class SomePoint implements Point {
x: 1;
y: 2;
}
type Point2 = {
x: number;
y: number;
};
class SomePoint2 implements Point2 {
x: 1;
y: 2;
}
type PartialPoint = { x: number; } | { y: number; };
// FIXME: can not implement a union type
class SomePartialPoint implements PartialPoint {
x: 1;
y: 2;
}
В отличие от псевдонима типа, интерфейс может быть определен несколько раз и будет рассматриваться как единый интерфейс (с элементами всех объединенных объявлений).
// These two declarations become:
// interface Point { x: number; y: number; }
interface Point { x: number; }
interface Point { y: number; }
const point: Point = { x: 1, y: 2 };
https://www.typescriptlang.org/docs/handbook/advanced-types.html
Одно отличие состоит в том, что интерфейсы создают новое имя, которое используется повсюду. Типа aliases не создают нового имени - например, сообщения об ошибках не будут использовать псевдоним.
Начиная с TypeScript 3.2, верно следующее: