TypeScript: Giao diện với các loại


Câu trả lời:


574

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ể.

109
"Khai báo nhiều sáp nhập" nghĩa là gì trong sự khác biệt thứ hai?
jrahhali

66
@jrahhali nếu bạn xác định giao diện hai lần, bản thảo sẽ hợp nhất chúng thành một.
Andrey Fedorov

39
@jrahhali nếu bạn xác định loại hai lần, bản đánh máy sẽ gây ra lỗi cho bạn
Andrey Fedorov

18
@jrahhaliinterface Point { x: number; } interface Point { y: number; }
Nahuel Greco

20
Tôi tin rằng điểm đầu tiên extends or implementskhô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/...
dark_ruby

776

Cập nhật 2019


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.

1. Đối tượng / Chức năng

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;

2. Các loại khác

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];

3. Mở rộng

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; };

4. Thực hiện

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;
}

5. Tuyên bố sáp nhập

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 };

9
Nếu tài liệu chính thức đã lỗi thời, thông tin bạn cung cấp có thể được xác nhận ở đâu?
iX3

59
Dựa trên bài đăng này, dường như lý do duy nhất để chọn giao diện trên bí danh loại là nếu bạn muốn sử dụng tính năng khai báo khai báo (điểm 5) của giao diện. Ngoài ra, chúng tương đương (và tôi cho rằng các bí danh loại cung cấp cú pháp ngắn gọn hơn).
maxedison

17
Tôi luôn luôn sử dụng các giao diện cho loại đối tượng, nếu không sử dụng các loại có ý nghĩa hơn, tôi cũng nghĩ rằng việc hợp nhất khai báo không nên được sử dụng trong bất kỳ cách nào, thực sự tôi sẽ không bao giờ nghĩ rằng một giao diện đang được khai báo trong một tệp khác của dự án với một số các thuộc tính bổ sung, kiểm tra loại được thực hiện ban đầu để làm cho cuộc sống của bạn dễ dàng hơn không làm khó hơn với các giao diện giống ninja này: D
Ahmed Kamal

8
Vì vậy, về cơ bản, đó là "gần như một lựa chọn cá nhân" cho những gì chúng ta thực sự cảm thấy thoải mái khi sử dụng? Ngoài một lý do, bạn chỉ có thể sử dụng typehay 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.
Joseph Briggs

7
Ai đó có thể vui lòng cung cấp một số động lực cho lý do tại sao bạn muốn hợp nhất giao diện? Điều đó dường như có thể gây nhầm lẫn với tôi. Tại sao bạn muốn truyền bá định nghĩa về giao diện của mình trên các khối khác nhau?
Vanquish46

95

Kể từ TypeScript 3.2 (tháng 11 năm 2018), điều sau đây là đúng:

nhập mô tả hình ảnh ở đây


9
Bạn có thể vui lòng cung cấp thêm thông tin về cách tạo bảng / hình ảnh bạn cung cấp không? ví dụ mã nguồn hoặc liên kết đến tài liệu
iX3

23
vâng, ý tôi là nguồn gốc của nội dung chứ không phải phần trình bày của nó.
iX3

3
Tôi không tin rằng một lớp có thể mở rộng một loại hoặc một giao diện, và tôi thực sự không thể hiểu tại sao bạn muốn ??
Dan King

7
Tránh đăng hình ảnh của văn bản, thay vào đó hãy bao gồm văn bản thực tế trực tiếp vào bài viết của bạn. Hình ảnh của văn bản không dễ dàng phân tích hoặc tìm kiếm được và người dùng khiếm thị không thể truy cập được.
Andrew Marshall

2
Bảng này thiếu bất kỳ nguồn nào để hỗ trợ nội dung của nó và tôi sẽ không dựa vào nó. Ví dụ: bạn có thể xác định các kiểu đệ quy bằng cách sử dụng typevớ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.
Michał Miszczyszyn


5

Ví dụ với các loại:

// 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;

Ví dụ với Giao diện:

// 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
    }


-2

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.

Giao diện so với loại bí danh

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.