В чем разница между этими утверждениями (интерфейс против типа)?
interface X {
a: number
b: string
}
type X = {
a: number
b: string
};
В чем разница между этими утверждениями (интерфейс против типа)?
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 или реализовать, но псевдоним типа для литерала типа объекта больше не может иметь значениеtrue, начиная с TS 2.7.- Интерфейс может иметь несколько объединенных объявлений , но псевдоним типа для литерала типа объекта не может.
interface Point { x: number; } interface Point { y: number; }
extends or implements
уже не тот. Тип может быть расширен и реализован с помощью class
. Вот пример typescriptlang.org/play/…
Текущие ответы и официальная документация устарели. А для новичков в 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 };
type
или interface
? Я все еще смущен, когда я должен использовать один или другой.
type
определенные ограничения (а в TypeScript 3.7 эти ограничения также исчезли). Интерфейсы могут расширять типы. Классы могут реализовывать типы. Кроме того, представление данных в виде скриншота таблицы делает ее полностью недоступной для людей с нарушениями зрения.
https://www.typescriptlang.org/docs/handbook/advanced-types.html
Одно отличие состоит в том, что интерфейсы создают новое имя, которое используется везде. Псевдонимы типа не создают новое имя - например, сообщения об ошибках не будут использовать имя псевдонима.
// создаем древовидную структуру для объекта. Вы не можете сделать то же самое с интерфейсом из-за отсутствия пересечения (&)
type Tree<T> = T & { parent: Tree<T> };
// введите, чтобы ограничить переменную, чтобы назначить только несколько значений. Интерфейсы не имеют объединения (|)
type Choise = "A" | "B" | "C";
// благодаря типам вы можете объявить тип NonNullable благодаря условному механизму.
type NonNullable<T> = T extends null | undefined ? never : T;
// вы можете использовать интерфейс для ООП и использовать «инструменты» для определения каркаса объекта / класса
interface IUser {
user: string;
password: string;
login: (user: string, password: string) => boolean;
}
class User implements IUser {
user = "user1"
password = "password1"
login(user: string, password: string) {
return (user == user && password == password)
}
}
// вы можете расширить интерфейсы с другими интерфейсами
interface IMyObject {
label: string,
}
interface IMyObjectWithSize extends IMyObject{
size?: number
}
В дополнение к блестящим ответам, уже предоставленным, есть заметные различия, когда речь идет о расширении типов по сравнению с интерфейсами. Недавно я столкнулся с парой случаев, когда интерфейс не может выполнить работу:
документация объяснила
- Одно отличие состоит в том, что интерфейсы создают новое имя, которое используется везде. Псевдонимы типов не создают новое имя - например, сообщения об ошибках не будут использовать псевдоним name. В более старых версиях TypeScript псевдонимы типов не могли быть расширены или реализованы (и при этом они не могли расширять / реализовывать другие типы). Начиная с версии 2.7, псевдонимы типов могут быть расширены путем создания нового типа пересечения
- С другой стороны, если вы не можете выразить какую-либо форму с помощью интерфейса, и вам необходимо использовать тип объединения или кортежа, обычно рекомендуется использовать псевдонимы типов.