Sự khác biệt giữa các tuyên bố này (giao diện so với loại) là gì?
interface X {
a: number
b: string
}
type X = {
a: number
b: string
};
Sự khác biệt giữa các tuyên bố này (giao diện so với loại) là gì?
interface X {
a: number
b: string
}
type X = {
a: number
b: string
};
Câu trả lời:
Theo Đặc tả ngôn ngữ TypeScript :
Không giống như một khai báo giao diện, luôn giới thiệu một loại đối tượng được đặt tên, một khai báo bí danh loại có thể giới thiệu một tên cho bất kỳ loại nào, bao gồm các loại nguyên thủy, hợp nhất và loại giao nhau.
Các đặc điểm kỹ thuật tiếp tục đề cập:
Các loại giao diện có nhiều điểm tương đồng với các bí danh loại cho các loại chữ đối tượng, nhưng vì các loại giao diện cung cấp nhiều khả năng hơn nên chúng thường được ưa thích hơn để nhập các bí danh. Ví dụ: loại giao diện
interface Point { x: number; y: number; }
có thể được viết dưới dạng bí danh
type Point = { x: number; y: number; };
Tuy nhiên, làm như vậy có nghĩa là các khả năng sau bị mất:
Một giao diện có thể được đặt tên trong một mệnh đề mở rộng hoặc thực hiện, nhưng một bí danh loại cho một loại đối tượng bằng chữcòn đúng kể từ TS 2.7.- Một giao diện có thể có nhiều khai báo được hợp nhất , nhưng một bí danh loại cho một loại đối tượng bằng chữ không thể.
interface Point { x: number; } interface Point { y: number; }
extends or implements
không còn là trường hợp. Loại có thể được mở rộng và thực hiện bởi a class
. Dưới đây là một ví dụ typescriptlang.org/play/...
Các câu trả lời hiện tại và các tài liệu chính thức đã lỗi thời. Và đối với những người mới sử dụng TypeScript, thuật ngữ được sử dụng không rõ ràng nếu không có ví dụ. Dưới đây là danh sách các sự khác biệt cập nhật.
Cả hai có thể được sử dụng để mô tả hình dạng của một đối tượng hoặc chữ ký hàm. Nhưng cú pháp khác nhau.
Giao diện
interface Point {
x: number;
y: number;
}
interface SetPoint {
(x: number, y: number): void;
}
Nhập bí danh
type Point = {
x: number;
y: number;
};
type SetPoint = (x: number, y: number) => void;
Không giống như một giao diện, bí danh loại cũng có thể được sử dụng cho các loại khác như nguyên thủy, đoàn thể và bộ dữ liệu.
// primitive
type Name = string;
// object
type PartialPointX = { x: number; };
type PartialPointY = { y: number; };
// union
type PartialPoint = PartialPointX | PartialPointY;
// tuple
type Data = [number, string];
Cả hai có thể được mở rộng, nhưng một lần nữa, cú pháp khác nhau. Ngoài ra, lưu ý rằng một giao diện và loại bí danh không loại trừ lẫn nhau. Một giao diện có thể mở rộng một bí danh loại và ngược lại.
Giao diện mở rộng giao diện
interface PartialPointX { x: number; }
interface Point extends PartialPointX { y: number; }
Loại bí danh mở rộng loại bí danh
type PartialPointX = { x: number; };
type Point = PartialPointX & { y: number; };
Giao diện mở rộng bí danh
type PartialPointX = { x: number; };
interface Point extends PartialPointX { y: number; }
Loại bí danh mở rộng giao diện
interface PartialPointX { x: number; }
type Point = PartialPointX & { y: number; };
Một lớp có thể thực hiện một giao diện hoặc nhập bí danh, cả hai theo cùng một cách chính xác. Tuy nhiên, lưu ý rằng một lớp và giao diện được coi là bản thiết kế tĩnh. Do đó, họ không thể thực hiện / mở rộng một bí danh loại đặt tên cho loại kết hợp.
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;
}
Không giống như một bí danh loại, một giao diện có thể được xác định nhiều lần và sẽ được coi là một giao diện duy nhất (với các thành viên của tất cả các khai báo được hợp nhất).
// 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
hay interface
? Tôi vẫn còn bối rối khi tôi nên sử dụng cái này hay cái khác.
type
với một số giới hạn nhất định (và kể từ TypeScript 3.7, các giới hạn này cũng không còn nữa). Giao diện có thể mở rộng các loại. Các lớp học có thể thực hiện các loại. Hơn nữa, việc trình bày dữ liệu dưới dạng ảnh chụp màn hình của bảng khiến nó hoàn toàn không thể truy cập được đối với những người có thị lực kém.
https://www.typescriptlang.org/docs/handbook/advified-types.html
Một sự khác biệt là các giao diện tạo ra một tên mới được sử dụng ở mọi nơi. Nhập bí danh không tạo tên mới - ví dụ: thông báo lỗi sẽ không sử dụng tên bí danh.
// tạo cấu trúc cây cho một đối tượng. Bạn không thể làm tương tự với giao diện vì thiếu giao lộ (&)
type Tree<T> = T & { parent: Tree<T> };
// gõ để hạn chế một biến chỉ gán một vài giá trị. Các giao diện không có liên minh (|)
type Choise = "A" | "B" | "C";
// nhờ các loại, bạn có thể khai báo loại NonNullable nhờ cơ chế có điều kiện.
type NonNullable<T> = T extends null | undefined ? never : T;
// bạn có thể sử dụng giao diện cho OOP và sử dụng 'implements' để xác định bộ xương đối tượng / lớp
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)
}
}
// bạn có thể mở rộng giao diện với các giao diện khác
interface IMyObject {
label: string,
}
interface IMyObjectWithSize extends IMyObject{
size?: number
}
Ngoài các câu trả lời xuất sắc đã được cung cấp, có những khác biệt đáng chú ý khi nói đến việc mở rộng các loại so với giao diện. Gần đây tôi gặp một vài trường hợp giao diện không thể thực hiện công việc:
tài liệu đã giải thích
- Một sự khác biệt là các giao diện tạo ra một tên mới được sử dụng ở mọi nơi. Các bí danh loại không tạo tên mới - ví dụ: thông báo lỗi sẽ không sử dụng tên bí danh. Trong các phiên bản cũ hơn của TypeScript, các bí danh loại không thể được mở rộng hoặc triển khai từ (chúng cũng không thể mở rộng / triển khai các loại khác). Kể từ phiên bản 2.7, các bí danh loại có thể được mở rộng bằng cách tạo loại giao lộ mới
- Mặt khác, nếu bạn không thể thể hiện một số hình dạng với một giao diện và bạn cần sử dụng kiểu kết hợp hoặc tuple, thì các bí danh thường là cách để sử dụng.