CODE VN

CODE VN

1645664700

Cách Sử Dụng Các Giao Diện Trong TypeScript

Giao diện TypeScript cung cấp một cách dễ dàng để chú thích các đối tượng, lớp và chức năng. Tìm hiểu giao diện là gì và cách sử dụng chúng.

TypeScript mang lại nhiều cải tiến hữu ích cho ngôn ngữ JavaScript. Một trong số đó là hệ thống gõ tĩnh có thể giúp bạn viết mã an toàn. Các giao diện là một phần của hệ thống gõ này. Hướng dẫn này sẽ giúp bạn hiểu giao diện TypeScript là gì và cách sử dụng chúng.

JavaScript, các đối tượng và thiên nga đen

Trong JavaScript và các nơi khác, các đối tượng là một trong những cách phổ biến nhất để nhóm các dữ liệu có liên quan lại với nhau và chuyển chúng đi khắp nơi. Vấn đề là, không có cách nào trong JavaScript để chỉ định đối tượng nhất định trông như thế nào. Không có cách nào để nói đối tượng nên có thuộc tính nào hoặc giá trị của chúng phải là gì.

Điều này làm cho nó dễ dàng tạo ra mã dễ bị lỗi. Ví dụ, để tạo một đối tượng và quên thêm một số thuộc tính. Sau đó, khi đến thời điểm cuối cùng sử dụng đối tượng đó, mã của bạn sẽ bị lỗi và chương trình sẽ bị treo. Lý do? Chương trình của bạn mong đợi thuộc tính cụ thể bị thiếu.

Vấn đề có thể không phải là một tài sản bị thiếu. Có thể loại giá trị của một số thuộc tính khác với những gì chương trình của bạn mong đợi. Kết quả thường giống nhau. Mã lỗi và chương trình bị treo. Người ta có thể lập luận rằng điều này không có khả năng xảy ra. Chà, động đất và lũ lụt cũng không có khả năng xảy ra.

Vấn đề là, không ai quan tâm đến xác suất khi những sự kiện này, những con thiên nga đen này , xảy ra. Người dùng của bạn sẽ không quan tâm rằng không đúng loại hoặc thiếu thuộc tính có thể không xảy ra khi ứng dụng họ đang sử dụng gặp sự cố. Giá như có một cách để tránh điều này. Có thể, TypeScript có thể giúp bạn ở đây.

Giao diện TypeScript trở nên đơn giản

Tính năng chính của TypeScript là hệ thống kiểu mạnh mẽ của nó. Hệ thống kiểu này cho phép bạn nhanh chóng chỉ định kiểu dữ liệu nguyên thủy cho các biến. Những kiểu đơn giản này chỉ là một phần của hệ thống kiểu này. TypeScript cũng cho phép bạn làm điều này với các đối tượng. Với sự trợ giúp của TypeScript, bạn có thể xác định hình dạng của bất kỳ đối tượng nào.

Hình dạng của một đối tượng chỉ định những thuộc tính mà một đối tượng nhất định chứa. Điều này cũng bao gồm các loại của chúng, loại nào nên giá trị của các thuộc tính này. Trong TypeScript, bạn có thể chỉ định hình dạng này thông qua giao diện. Giao diện TypeScript là các kiểu trừu tượng. Các giao diện nói với trình biên dịch hai điều quan trọng.

Đầu tiên, các giao diện cho biết những thuộc tính mà một đối tượng nhất định có thể có hoặc phải có. Điều này có nghĩa là khi một số thuộc tính là tùy chọn, TypeScript sẽ biết rằng những thuộc tính này là không bắt buộc và sẽ không yêu cầu bạn xác định chúng. Thứ hai, các giao diện chỉ định kiểu của các thuộc tính này, kiểu giá trị của chúng.

Với thông tin này, TypeScript có thể cảnh báo bạn khi bạn vô tình xác định một số thuộc tính đối tượng và sử dụng sai kiểu. TypeScript sẽ biết loại nào được mong đợi sẽ được sử dụng cho mỗi thuộc tính đối tượng. Nếu bạn sử dụng loại khác, TypeScript sẽ cho bạn biết về sự không khớp, nơi nó xảy ra và cũng như cách khắc phục nó.

Tạo giao diện

Khi bạn muốn tạo một giao diện mới, bạn thực hiện bằng cách sử dụng interfacetừ khóa. Từ khóa này được theo sau bởi tên của giao diện thêm dấu ngoặc nhọn. Các dấu ngoặc này chứa hình dạng của một đối tượng, các thuộc tính và kiểu của nó. Bạn chỉ định các thuộc tính và kiểu này dưới dạng cặp khóa: giá trị.

Điều này rất giống với việc tạo đối tượng mới theo nghĩa đen . Tuy nhiên, có một số khác biệt. Đầu tiên, không có dấu bằng giữa tên của giao diện và dấu ngoặc nhọn. Thứ hai, các cặp khóa: giá trị được phân tách bằng dấu chấm phẩy. Dưới đây là các ví dụ về giao diện TypeScript đơn giản.

// Create an empty interface:
interface EmptyObject {}

// Create interface Cat:
interface Cat {
  name: string;
  age: number;
  hairColor: string;
  weight: number;
  height: number;
}

// Create interface Car:
interface Car {
  model: string;
  manufacturer: string;
  numberOfWheels: number;
  type: string;
}

// Create interface User:
interface User {
  username: string;
  password: string;
  email: string;
  isActive: boolean;
  role: 'admin' | 'user' | 'guest';
}

Giao Catdiện xác định một đối tượng có năm thuộc tính : name,, và . Tất cả các thuộc tính này là bắt buộc. Giá trị của và phải là chuỗi. Phần còn lại phải là số. Giao diện xác định một đối tượng có bốn thuộc tính :, và .agehairColorweightheightnamehairColorCarmodelmanufacturernumberOfWheelstype

Các thuộc tính này cũng là bắt buộc. Giá trị của numberOfWheelsphải là một số. Phần còn lại phải là chuỗi. Cuối cùng, Usergiao diện xác định một đối tượng có lại năm thuộc tính : username,, và . Giá trị của ba giá trị đầu tiên phải là chuỗi.passwordemailisActiverole

Giá trị của thuộc isActivetính phải là boolean, đúng hoặc sai. Giá trị của rolelà cụ thể hơn. Nó nói rằng giá trị phải là một trong ba chuỗi sau 'admin': 'user'hoặc 'guest'. Nếu bạn sử dụng bất kỳ chuỗi nào khác, TypeScript sẽ cảnh báo bạn rằng giá trị bạn sử dụng là sai, mặc dù kiểu là giống nhau.

Giao diện ngầm định

Giao diện TypeScript không nhất thiết phải do bạn tạo ra một cách rõ ràng. TypeScript cũng sẽ tự tạo giao diện khi bạn xác định một đối tượng. TypeScript sẽ xem xét các thuộc tính của đối tượng đó và giá trị của các thuộc tính này. Sau đó, nó sẽ suy ra các kiểu cụ thể bằng cách sử dụng suy luận kiểu.

Kết quả sẽ là giao diện ngầm phù hợp với đối tượng bạn vừa tạo. Điều này cũng áp dụng nếu bạn tạo đối tượng rỗng, không có bất kỳ thuộc tính nào. TypeScript sẽ chỉ tạo một giao diện trống. Điều này sau đó có thể gây ra sự cố khi bạn cố gắng thêm các thuộc tính vì TypeScript sẽ mong đợi đối tượng là và vẫn trống.

Một cách đơn giản để tránh điều này là tự bạn xác định các giao diện một cách rõ ràng. Nếu bạn tạo một đối tượng trống cũng tạo một giao diện cho nó. Giao diện này sẽ không chỉ định hình dạng hiện tại của đối tượng mà là hình dạng của nó trong tương lai. Điều này sẽ cho TypeScript biết những thuộc tính và kiểu nào được mong đợi.

Sử dụng giao diện

Khi bạn tạo một giao diện, bạn cũng phải cho TypeScript biết bạn định sử dụng nó cho đối tượng nào. Làm như vậy là dễ dàng. Khi bạn gán một đối tượng cho một biến, bạn có thể chỉ định giao diện của nó bằng cách thêm dấu hai chấm và tên của giao diện giữa tên biến và dấu bằng.

// Create an interface User:
interface User {
  password: string;
  email: string;
  role: 'admin' | 'user' | 'guest';
  logUserData: () => string;
}

// Use interface to annotate an object:
const userJoe: User = {
  password: 'some_secret_password123645',
  email: 'joe@user.co',
  role: 'user',
  logUserData: () => `${email}, ${role}`
}

Điều này cũng áp dụng ở những nơi khác. Nếu bạn muốn sử dụng một giao diện cho một đối tượng được sử dụng làm tham số hàm, bạn sử dụng cách tiếp cận tương tự. Bạn chỉ định tham số, sau đó thêm dấu hai chấm, rồi bạn chỉ định giao diện.

// Create an interface User:
interface User {
  password: string;
  email: string;
  role: 'admin' | 'user' | 'guest';
  logUserData: () => string;
}

// Create a function with "user" parameter
// and annotate the "user" parameter with "User" interface.
function getUserEmail(user: User) {
  return user.email
}

Triển khai giao diện với các lớp

TypeScript cũng cho phép bạn sử dụng giao diện với các lớp JavaScript . Tuy nhiên, với các lớp, việc triển khai hơi khác một chút. Bạn vẫn chỉ định giao diện sau tên, tên lớp trong trường hợp này. Tuy nhiên, bạn không đặt dấu hai chấm giữa tên của lớp và giao diện.

Thay vào đó, những gì bạn làm về cơ bản là thay thế các dấu hai chấm đó bằng implementstừ khóa. Điều này sẽ cho TypeScript biết rằng một lớp nhất định nên sử dụng một giao diện theo sau từ khóa này.

// Create interface Person:
interface Person {
  // Define some class properties
  // of type string and number:
  firstName: string;
  lastName: string;
  age: number;
  gender: 'male' | 'female';
  // Define class method that returns a string:
  sayHello: () => string;
}

// Annotate class "Female" with "Person" interface:
class Female implements Person {
  // Define required public properties:
  firstName: string
  lastName: string
  age: number
  gender: 'male' | 'female'

  // Create constructor and assign existing properties:
  constructor(firstName: string, lastName: string, age: number, gender: 'male' | 'female') {
    this.firstName = firstName
    this.lastName = lastName
    this.age = age
    this.gender = gender
  }

  // Define required class method:
  sayHello() {
    return `Hello, my name is ${this.firstName}.`
  }
}

Chỉ định các thuộc tính tùy chọn

Cho đến nay, tất cả các ví dụ chúng tôi đang sử dụng chỉ sử dụng các thuộc tính bắt buộc. Điều này sẽ hiệu quả đối với nhiều trường hợp. Tuy nhiên, nó có thể xảy ra rằng bạn có thể không cần một số thuộc tính trong một đối tượng nhất định mọi lúc. Một điều bạn có thể làm là tạo một giao diện mới, không có các thuộc tính tùy chọn. Sau đó, bạn có thể chuyển đổi giữa các giao diện này khi cần.

Điều này sẽ hiệu quả, nhưng nó cũng sẽ dẫn đến trùng lặp và nhiều mã hơn để duy trì. Có một điều khác bạn có thể làm. Bạn có thể lấy giao diện ban đầu và đánh dấu các thuộc tính tùy chọn là tùy chọn. Bạn đạt được điều này bằng cách đặt dấu chấm hỏi ( ?) giữa tên thuộc tính và dấu hai chấm.

// Create an interface with optional properties:
interface Person {
  firstName: string;
  lastName: string;
  middleName?: string; // <= This property will be optional
}

// This will work:
const bill: Person = {
  firstName: 'Bill',
  lastName: 'Doherty',
  middleName: 'Stevens'
}

// This will also work because "middleName"
// property is not required:
const will: Person = {
  firstName: 'William',
  lastName: 'Connors',
}

// This will not work because "lastName"
// property is required but missing:
const jack: Person = {
  firstName: 'Jack',
  middleName: 'O\'Conor',
}
// TS error: Property 'lastName' is missing in type '{ firstName: string; middleName: string; }' but required in type 'Person'.

Chỉ định thuộc tính chỉ đọc

Khi bạn tạo một đối tượng, bạn có thể muốn ngăn một số thuộc tính bị thay đổi. Bạn cũng có thể chỉ định ý định này thông qua các giao diện TypeScript. Bạn đạt được điều này bằng cách đặt readonlytừ khóa trước tên tài sản. Điều này sẽ cho TypeScript biết rằng thuộc tính theo sau là thuộc tính chỉ đọc.

Nếu bạn sử dụng giao diện để chú thích một số đối tượng, bạn sẽ có thể đặt giá trị cho thuộc tính chỉ đọc trong quá trình khởi tạo. Nếu bạn cố gắng thay đổi giá trị thuộc tính sau đó, trình biên dịch TypeScript sẽ báo lỗi.

// Create interface with read-only property:
interface User {
  username: string;
  password: string;
  readonly email: string; // <= This property will be read-only
}

// Annotate object "userFrank" with "User" interface:
const userFrank: User = {
  username: 'frankie',
  password: '123456782',
  email: 'frankie@frank.com'
}

// Try to change value of "username" property:
userFrank.username = 'frankman'

// Try to change value of "email" property:
userFrank.email = 'frankman@frank.com'
// TS error: Cannot assign to 'email' because it is a read-only property.

Giao diện cho các chức năng

Các đối tượng, bao gồm cả các lớp, không phải là những thứ duy nhất có thể sử dụng giao diện. Bạn cũng có thể sử dụng giao diện TypeScript để chú thích các chức năng. Bạn có thể làm điều này bằng cách cung cấp cho giao diện một chữ ký cuộc gọi. Điều này có nghĩa là bạn sẽ chỉ xác định danh sách tham số và kiểu trả về của hàm.

// Create interface for multiply function:
interface MultiplyFunc {
  // Specify only parameters and return type:
  (a: number, b: number): number;
}

// Annotate the "multiply" function
// with "MultiplyFunc" interface:
const multiply: MultiplyFunc = (a, b) => {
  return a * b
}

// Note:
// Thanks to MultiplyFunc interface TypeScript
// will know that "a" and "b" in "multiply" function
// are numbers so you don't have to type them explicitly.

Một điều về giao diện và chức năng. Tên của tham số trong giao diện không nhất thiết phải khớp với tên của tham số trong hàm thực tế. Bạn có thể sử dụng một tên cho tham số giao diện và một tên khác cho khai báo hàm. TypeScript sẽ kết nối các tham số với các loại của chúng một cách chính xác bằng cách sử dụng thứ tự của chúng.

interface MyFunc {
  // Specify only parameters and return type:
  (a: number, b: string, c: boolean): string;
}

// Annotate the "multiply" function
// with "MultiplyFunc" interface:
const myFunc: MyFunc = (a, b, c) => {
  return `a is ${a}, b is ${b}, c is ${c}`
}
// TypeScript will correctly infer "a" to be number,
// "b" to be string and "c" to be boolean.

Mở rộng giao diện

Một điều hữu ích là các giao diện cho phép mở rộng, giống như các lớp JavaScript. Giả sử bạn có một giao diện hiện có. Bạn cũng có một đối tượng, nhưng đối tượng này chứa nhiều thuộc tính hơn giao diện chỉ định. Một điều bạn có thể làm là thay đổi giao diện để phù hợp với đối tượng này.

Vấn đề là điều này sẽ ảnh hưởng đến tất cả các đối tượng sử dụng giao diện đó. Một thứ khác là tạo giao diện mới, sao chép giao diện cũ và thêm các thuộc tính mới. Điều này sẽ làm cho mã của bạn bị trùng lặp. May mắn thay, có tùy chọn thứ ba. Bạn có thể tạo giao diện mới và mở rộng nó với giao diện gốc.

Bằng cách này, giao diện mới sẽ kế thừa tất cả các thuộc tính được xác định trong giao diện ban đầu. Phần tốt nhất? Bạn sẽ không phải sao chép một dòng mã nào. Bạn có thể mở rộng giao diện bằng cách sử dụng extendstừ khóa. Từ khóa này cho phép bạn mở rộng một giao diện chỉ với một giao diện cũng như với nhiều giao diện.

Khi bạn muốn mở rộng giao diện với nhiều giao diện, bạn phân tách chúng bằng dấu phẩy. Từ extendskhóa nằm giữa giao diện đầu tiên, giao diện bạn đang mở rộng và giao diện thứ hai, giao diện bạn đang mở rộng.

// Create "Person" interface:
interface Person {
  name: string;
}

// Create "Male" interface that extends "Person" interface:
interface Male extends Person {
  gender: 'Male';
}
// Basically translates to:
// interface Male {
//   name: string;
//   gender: 'Male';
// }

// Create "Female" interface that also extends "Person" interface:
interface Female extends Person {
  gender: 'Female';
}
// Basically translates to:
// interface Female {
//   name: string;
//   gender: 'Female';
// }

// Create "Boy" interface that extends "Person" and "Male" interfaces:
interface Boy extends Person, Male {
  age: number;
}
// Basically translates to:
// interface Boy {
//   name: string;
//   gender: 'Male';
//   age: number;
// }

// Create "Girl" interface that extends "Person" and "Female" interfaces:
interface Girl extends Person, Female {
  age: number;
}
// Basically translates to:
// interface Girl {
//   name: string;
//   gender: 'Female';
//   age: number;
// }

const stanley: Person = {
  name: 'Stanley'
}

const david: Male = {
  name: 'David',
  gender: 'Male'
}

const sarah: Female = {
  name: 'Sarah',
  gender: 'Female'
}

const andreas: Boy = {
  name: 'Andreas',
  gender: 'Male',
  age: 13
}

const victoria: Girl = {
  name: 'Victoria',
  gender: 'Female',
  age: 6
}

Tạo giao diện chung

Một điều nữa. TypeScript cũng cho phép tạo một thứ gọi là “giao diện chung”. Các giao diện này cho phép bạn chỉ định loại thuộc tính dựa trên một hoặc nhiều tham số mà bạn cung cấp cho giao diện khi sử dụng. Bạn có thể chỉ định các tham số này bằng cách sử dụng dấu ngoặc nhọn ( <>) như trong ví dụ bên dưới.

// Create interface for UserData:
interface UserData {
  name: string;
  email: string;
}

// Create a generic interface:
interface ApiResponse<T> {
  date: Date;
  code: number;
  payload: T[];
}

// Create function to fetch API
async function fetchAPI() {
  // Use ApiResponse "interface" and pass
  // the "UserData" interface as argument (for T argument):
  const data: ApiResponse<UserData> = await fetch('/some_api_endpoint')

  // The "ApiResponse<UserData>" basically translates to:
  // interface ApiResponse<T> {
  //   date: Date;
  //   code: number;
  //   payload: UserData[];

  //   Or:
  //   payload: [name: string; email: string;]
  // }
}

Kết Luận: 

Giao diện TypeScript cung cấp một cách dễ dàng để chú thích các đối tượng của bạn, bao gồm các lớp và cả các hàm. Điều này có thể giúp bạn viết mã an toàn hơn và dễ bảo trì hơn. Tôi hy vọng rằng hướng dẫn này đã giúp bạn hiểu và tìm hiểu về giao diện là gì và cách sử dụng chúng trong mã của bạn.

What is GEEK

Buddha Community

The Definitive Guide to TypeScript & Possibly The Best TypeScript Book

TypeScript Deep Dive

I've been looking at the issues that turn up commonly when people start using TypeScript. This is based on the lessons from Stack Overflow / DefinitelyTyped and general engagement with the TypeScript community. You can follow for updates and don't forget to ★ on GitHub 🌹

Reviews

  • Thanks for the wonderful book. Learned a lot from it. (link)
  • Its probably the Best TypeScript book out there. Good Job (link)
  • Love how precise and clear the examples and explanations are! (link)
  • For the low, low price of free, you get pages of pure awesomeness. Chock full of source code examples and clear, concise explanations, TypeScript Deep Dive will help you learn TypeScript development. (link)
  • Just a big thank you! Best TypeScript 2 detailed explanation! (link)
  • This gitbook got my project going pronto. Fluent easy read 5 stars. (link)
  • I recommend the online #typescript book by @basarat you'll love it.(link)
  • I've always found this by @basarat really helpful. (link)
  • We must highlight TypeScript Deep Dive, an open source book.(link)
  • Great online resource for learning. (link)
  • Thank you for putting this book together, and for all your hard work within the TypeScript community. (link)
  • TypeScript Deep Dive is one of the best technical texts I've read in a while. (link)
  • Thanks @basarat for the TypeScript Deep Dive Book. Help me a lot with my first TypeScript project. (link)
  • Thanks to @basarat for this great #typescript learning resource. (link)
  • Guyz excellent book on Typescript(@typescriptlang) by @basarat (link)
  • Leaning on the legendary @basarat's "TypeScript Deep Dive" book heavily at the moment (link)
  • numTimesPointedPeopleToBasaratsTypeScriptBook++; (link)
  • A book not only for typescript, a good one for deeper JavaScript knowledge as well. link
  • In my new job, we're using @typescriptlang, which I am new to. This is insanely helpful huge thanks, @basarat! link
  • Thank you for writing TypeScript Deep Dive. I have learned so much. link
  • Loving @basarat's @typescriptlang online book basarat.gitbooks.io/typescript/# loaded with great recipes! link
  • Microsoft doc is great already, but if want to "dig deeper" into TypeScript I find this book of great value link
  • Thanks, this is a great book 🤓🤓 link
  • Deep dive to typescript is awesome in so many levels. i find it very insightful. Thanks link
  • @basarat's intro to @typescriptlang is still one of the best going (if not THE best) link
  •  
  • This is sweet! So many #typescript goodies! link

Get Started

If you are here to read the book online get started.

Translations

Book is completely free so you can copy paste whatever you want without requiring permission. If you have a translation you want me to link here. Send a PR.

Other Options

You can also download one of the Epub, Mobi, or PDF formats from the actions tab by clicking on the latest build run. You will find the files in the artifacts section.

Special Thanks

All the amazing contributors 🌹

Share

Share URL: https://basarat.gitbook.io/typescript/

Author: Basarat
Source Code: https://github.com/basarat/typescript-book/ 
License: View license

#typescript #opensource 

Hoang  Ha

Hoang Ha

1658401200

Sử Dụng Các Loại Giao Điểm để Kết Hợp Các Loại Trong TypeScript

TypeScript cho phép chúng ta không chỉ tạo các kiểu riêng lẻ mà còn kết hợp chúng để tạo ra các trường hợp sử dụng mạnh mẽ hơn và tính hoàn chỉnh hơn.

Có một khái niệm được gọi là “Các kiểu giao nhau” trong TypeScript về cơ bản cho phép chúng ta kết hợp nhiều kiểu.

Các kiểu giao nhau cho phép chúng tôi sử dụng lại các định nghĩa kiểu hiện có từ bất kỳ đâu và tạo các kết hợp mới của chúng.

Giả sử chúng ta có một thanh toán chấp nhận cả Stripe và PayPal làm nhà cung cấp thanh toán, chúng ta có thể bắt đầu với một Ordergiao diện:

interface Order {
  total: number;
  currency: string;
}

Sau đó, chúng tôi có thể mở rộng nó để thêm các nhà cung cấp thanh toán và liệu chúng tôi có sử dụng chúng hay không:

// ❌ Not a great approach, but works
interface Order {
  total: number;
  currency: string;
  paypal?: boolean;
  stripe?: boolean;
}

Điều này tạo ra một thuộc tính tùy chọn trên mỗi loại. Cá nhân tôi không phải là một fan hâm mộ của cách tiếp cận này, vì vậy có lẽ chúng tôi có thể cải thiện nó thông qua một loại liên minh:

// ❌ Not a great approach, but works
interface Order {
  total: number;
  currency: string;
  provider: 'stripe' | 'paypal';
}

Tốt hơn? Cho đến nay, có! Nhưng bây giờ chúng ta cần lấy thông tin khác nhau dựa trên nhà cung cấp dịch vụ thanh toán.

Giả sử phương pháp Stripe sử dụng thuộc tính thẻ tín dụng và PayPal sử dụng email.

Sau đó, điều này sẽ đưa chúng ta trở lại ô vuông một, vì sau đó chúng ta phải đặt trường thẻ tín dụng và địa chỉ email (được sử dụng cho PayPal) là tùy chọn:

// ❌ Not a great approach, but works
interface Order {
  total: number;
  currency: string;
  provider: 'stripe' | 'paypal';
  card?: number;
  email?: string;
}

Vậy chúng ta có thể làm gì? Tạo nhiều kiểu cơ bản hơn. Nhập, loại giao lộ.

Điều này không chỉ dễ thực hiện mà còn là một mẫu dễ đọc và dễ mở rộng hơn rất nhiều.

Thêm vào đó, nó để lại ít chỗ cho lỗi hơn, vì không có trường nào là "tùy chọn".

Hãy chia mọi thứ thành nhiều loại hơn:

// ✅ Getting better...
interface Order {
  total: number;
  currency: string;
}

interface Stripe { card: number; }
interface PayPal { email: string; }

Có vẻ dễ dàng hơn để tiêu hóa những gì đang xảy ra, tôi thích nó. Hãy tiến về phía trước và kết hợp chúng sau đó.

Một loại giao lộ được xác định bằng cách sử dụng &ký tự dấu và, giúp bạn hiểu rõ điều gì đang xảy ra.

Giao lộ trả về một kiểu hoàn toàn mới, được kết hợp. Đối với điều này, chúng tôi typecũng sẽ sử dụng từ khóa thay vì interface:

interface Order {
  total: number;
  currency: string;
}

interface Stripe { card: number; }
interface PayPal { email: string; }

type StripeOrder = Order & Stripe; // { total: number; currency: string; card: number; }
type PayPalOrder = Order & PayPal; // { total: number; currency: string; email: string; }

Hãy chú ý đến các định nghĩa kiểu mới, tôi đã thêm chúng là gì trong các nhận xét. Xinh đẹp!

Điều này siêu sạch và cho phép chúng tôi tạo logic đơn giản hơn ở những nơi khác trong ứng dụng của mình, thay vì các thuộc tính tùy chọn phát hiện hack, v.v.

Sau đó, điều này có thể được kết hợp với Literal Type Guard để tạo ra một giải pháp được đánh máy được suy luận:

interface Order {
  total: number;
  currency: string;
}

interface Stripe { card: number; }
interface PayPal { email: string; }

type StripeOrder = Order & Stripe;
type PayPalOrder = Order & PayPal;

const isStripe = (order: StripeOrder | PayPalOrder): order is StripeOrder => {
  return 'card' in (order as StripeOrder);
};

const processOrder = (order: StripeOrder | PayPalOrder) => {
  if (isStripe(order)) {
    // ✅ order.card
    // ❌ order.email
  } else {
    // ✅ order.email
    // ❌ order.card
  }
};

Và thế là xong, một ví dụ nhỏ hay về việc hợp nhất các kiểu trong TypeScript để tạo ra nhiều kiểu hơn!

Cảm ơn vì đã đọc!

Nguồn: https://ultimatecourses.com/blog/use-intersection-types-to-combine-types-in-typescript

#typescript 

CODE VN

CODE VN

1645603292

Cách Sử Dụng Các giao diện trong TypeScript

Tìm hiểu cách sử dụng các hàm trong TypeScript. Tìm hiểu cách xác định kiểu cho tham số và kiểu trả về, cách tạo kiểu hàm và hơn thế nữa.

Các hàm là một phần cơ bản của JavaScript. Chúng giúp làm cho mã có thể tái sử dụng trong khi vẫn giữ cho nó linh hoạt. TypeScript nâng cao những lợi ích này bằng cách giúp bạn viết các hàm an toàn cho kiểu gõ. Hướng dẫn này sẽ chỉ cho bạn cách sử dụng các hàm trong TypeScript, cách chỉ định kiểu cho các tham số, kiểu trả về và hơn thế nữa.

Không có gì mới, chỉ an toàn hơn?

Các hàm là một trong những tính năng ngôn ngữ được sử dụng thường xuyên nhất. Điều này không chỉ áp dụng cho JavaScript và TypeScript, mà còn cho các ngôn ngữ lập trình khác. Trong JavaScript, có một vấn đề. JavaScript không phải là một ngôn ngữ lập trình kiểu tĩnh. Bởi vì điều này, có một số điều bạn không thể làm.

Ví dụ: khi bạn xác định một hàm, bạn không thể chỉ định các kiểu được phép cho các tham số của nó. Điều này làm cho việc gọi một hàm có đối số sai kiểu dễ dàng hơn. Bạn có thể tạo một hàm nhận hai số làm tham số và gọi nó truyền hai chuỗi làm đối số. JavaScript sẽ không ngăn cản bạn.

Bạn cũng không thể chỉ định kiểu trả về của một hàm. Điều này có thể dẫn đến các vấn đề khi một phần của chương trình gọi một hàm mong đợi nhận được một thứ trong khi hàm trả về một thứ khác. Đây là nơi mà TypeScript có thể hữu ích. Đúng là TypeScript không thực sự thêm bất cứ điều gì mới vào các hàm.

Các chức năng trong TypeScript vẫn là các chức năng, những chức năng đó bạn biết từ JavaScript. Những gì TypeScript làm là nó làm cho các chức năng an toàn hơn, dễ dự đoán hơn. Nó làm như vậy bằng cách kết hợp các chức năng với hệ thống kiểu mạnh mẽ của nó. Điều này giúp bạn đảm bảo các chức năng của bạn nhận và trả về đúng loại. Chúng ta hãy xem làm thế nào.

Các loại tham số

Khi bạn tạo một hàm, bạn cũng có thể chỉ định bất kỳ tham số nào mà nó chấp nhận. Điều này làm cho mã của bạn linh hoạt hơn và dễ dàng sử dụng lại trong các điều kiện khác nhau. Với TypeScript, bạn cũng có thể chỉ định kiểu cho các tham số này. Khi bạn cố gắng gọi bất kỳ hàm nào có đối số không đúng kiểu, TypeScript sẽ cảnh báo bạn.

Cú pháp để xác định kiểu cho các tham số hàm rất đơn giản. Nó bao gồm dấu hai chấm ( :) và kiểu. Đầu tiên, bạn xác định một tham số. Sau đó, bạn thêm dấu hai chấm ngay sau nó. Sau đó, bạn chỉ định loại nào được phép cho tham số cụ thể đó.

// Create a function that accepts two parameters: str1 and str2.
// Both parameters must be of type string.
function joinStrings(str1: string, str2: string) {
  return str1 + str2
}

// This will work:
joinStrings('Wo', 'rld')
// Output:
// 'World'

// This will not work:
joinStrings('Hel', 135)
// TS error: Argument of type 'number' is not assignable to parameter of type 'string'.

TypeScript cũng cho phép bạn chỉ định nhiều kiểu. Bạn có thể đạt được điều này bằng cách sử dụng các loại liên hợp . Về cơ bản, điều này có nghĩa là bạn có thể sử dụng hai hoặc nhiều loại và nói với TypeScript rằng bất kỳ loại nào trong số này đều có thể được sử dụng. Khi bạn muốn sử dụng các kiểu liên hợp, bạn chỉ định tất cả các kiểu có thể có và sử dụng |để tách chúng.

// Create a function that accepts one parameter.
// This parameter can be either number, string or boolean.
function numStrBool(val: number | string | boolean) {
  return typeof val
}

// This will work in TypeScript:
numStrBool(15)
// Output:
// 'number'

// This will also work in TypeScript:
numStrBool('Tea')
// Output:
// 'string'

// This will also work in TypeScript:
numStrBool(true)
// Output:
// 'boolean'

// This will not work in TypeScript:
numStrBool({ key: 15 })
// TS error: Argument of type '{ key: number; }' is not assignable to parameter of type 'string | number | boolean'.

Các thông số tùy chọn

Cũng giống như trong JavaScript, bạn cũng có thể đánh dấu một số tham số là tùy chọn trong TypeScript. Cú pháp giống nhau. Để đánh dấu một tham số là tùy chọn, bạn thêm dấu chấm hỏi ( ?) ngay sau nó. Khi bạn làm việc với các hàm trong TypeScript, dấu chấm hỏi đi sau tên tham số và trước dấu hai chấm và kiểu.

// Create a function that accepts two parameters,
// the first one required and the second optional:
function combineWords(word1: string, word2?: string) {
  return `${word1}${word2 ? word2 : ''}`
}

// This will work in TypeScript:
combineWords('Hello', 'world')
// Output:
// 'Helloworld'

// This will also work in TypeScript:
combineWords('Say', 'Bye')
// Output:
// 'SayBye'

// This will also work in TypeScript:
combineWords('Hi')
// Output:
// 'Hi'

// This will not work in TypeScript:
combineWords()
// TS error: Expected 1-2 arguments, but got 0.

Các thông số mặc định

TypeScript cũng cho phép bạn xác định các giá trị mặc định cho các tham số hàm. Đó không phải là tất cả. Khi bạn xác định các giá trị mặc định cho các hàm trong TypeScript, bạn không cần phải chỉ định rõ ràng các kiểu cho các tham số này. TypeScript sẽ có thể sử dụng các giá trị mặc định để suy ra các loại cho các tham số một cách tự động. Ít công việc hơn cho bạn.

Cú pháp cho các giá trị mặc định giống như trong JavaScript . Bạn chỉ định một tham số và ngay sau nó, thêm một dấu bằng với giá trị mặc định. Nếu bạn cũng muốn chỉ định rõ ràng một kiểu cho tham số, bạn chỉ định kiểu trước. Điều này có nghĩa là sử dụng thứ tự sau: tên tham số, dấu hai chấm và kiểu, dấu bằng và giá trị mặc định.

// Example 1: default parameters and implicit type:
// Create a function that accepts two parameters.
// Both parameters are of type numbers,
// the second has default value 0.
function addTwoNumbers(num1: number, num2 = 0) {
  return num1 + num2
}
// TS will add type for num2 implicitly:
// addTwoNumbers(num1: number, num2: number = 0)

// This will work in TypeScript:
addTwoNumbers(98, 656)
// Output:
// 754

// This will also work in TypeScript:
addTwoNumbers(63)
// Output:
// 63

// This will not work in TypeScript:
addTwoNumbers('13')
// TS error: Argument of type 'string' is not assignable to parameter of type 'number'.


// Example 2: default parameters and explicit type:
function addTwoNumbers(num1: number, num2: number = 0) {
  return num1 + num2
}

Các thông số còn lại

Một số hàm có thể chấp nhận một số lượng đối số tùy ý. Đây là nơi mà cú pháp tham số phần còn lại sẽ rất hữu ích. Trong TypeScript, bạn có thể chỉ định kiểu cho các tham số còn lại dễ dàng như bất kỳ tham số nào khác. Cú pháp giống nhau. Bạn thêm tham số còn lại và theo sau nó bằng dấu hai chấm và kiểu.

Khi bạn làm việc với các tham số nghỉ, hãy nhớ một điều. Các tham số được truyền dưới dạng tham số còn lại sẽ được thu thập trong một mảng. Điều này có nghĩa là bạn cũng phải sử dụng kiểu mảng, type[]hoặc Array<type>.

// Create a function that accepts two parameters.
// The first parameter is a string.
// The second is a rest parameter and is an array of strings.
function buildATeam(leader: string, ...teammates: string[]) {
  return `Team is composed of ${leader} as a the team leader and ${teammates.length > 0 ? teammates.join(', ') : 'nobody'} as the core team.`
}

// This will work in TypeScript:
buildATeam('Joe', 'Vicky', 'Thomas')
// Output:
// 'Team is composed of Joe as a the team leader and Vicky, Thomas as the core team.'

// This will also work in TypeScript:
buildATeam('Sandra', 'Alex', 'Jack', 'Victor')
// Output:
// 'Team is composed of Sandra as a the team leader and Alex, Jack, Victor as the core team.'

// This will also work in TypeScript:
buildATeam('Stuart')
// Output:
// 'Team is composed of Stuart as a the team leader and nobody as the core team.'

// This will not work in TypeScript:
buildATeam(13, 15)
// TS error: Argument of type 'number' is not assignable to parameter of type 'string'.

Trả lại các loại

TypeScript cũng cho phép bạn chỉ định kiểu trả về của một hàm. Điều đó nói rằng, bạn sẽ không thấy mình làm điều này thường xuyên. Trong hầu hết các trường hợp, TypeScript sẽ có thể suy ra kiểu trả về của hàm dựa trên các câu lệnh trả về bên trong chính hàm. Bạn không cần phải chỉ định các loại này một cách rõ ràng.

Điều gì sẽ xảy ra nếu TypeScript không thể suy ra kiểu trả về hoặc bạn muốn tự mình chỉ định? Để chỉ định kiểu trả về của hàm, bạn phải thêm dấu hai chấm và kiểu ngay sau danh sách tham số, trước thân hàm.

// Create a function that accepts two parameters.
// Both parameters are numbers.
// Set the return type to be a number (the '): number {' part).
function numToPow(num: number, exp: number): number {
  return num ** exp
}

// This will work in TypeScript:
numToPow(15, 8)
// Output:
// 2562890625

// This will not work in TypeScript:
numToPow(12, '9')
// TS error: Argument of type 'string' is not assignable to parameter of type 'number'.

Các loại chức năng

Khi bạn làm việc với các hàm trong TypeScript, bạn thường xác định tất cả các kiểu của nó khi bạn khai báo một hàm. Điều mà TypeScript cũng cho phép là xác định một chữ ký hàm trước khi bạn thực sự tạo chính hàm. Sau đó, khi bạn tạo hàm, TypeScript sẽ sử dụng chữ ký để tự động suy ra tất cả các kiểu cho bạn.

Chữ ký này được gọi là một kiểu hàm. Nó có thể hữu ích khi bạn mong đợi một chữ ký chức năng cụ thể. Loại hàm này bao gồm hai phần: tham số và kiểu trả về. Khi bạn khai báo một kiểu hàm, bạn phải chỉ định cả hai phần này.

// Create function type for function subtract.
// This function accepts two parameters, both are numbers.
// Its return type is also a number.
let subtract: (a: number, b: number) => number

// Assign the actual function to the variable:
subtract = function (a, b) {
  return a - b
}

// This will not work in TypeScript:
subtract = function (a: string, b: string) {
  return a + b
}
// TS error: Type '(a: string, b: string) => string' is not assignable to type '(a: number, b: number) => number'.

Hãy nhớ rằng khi bạn khai báo kiểu hàm, bạn không phải chỉ định lại các kiểu khi bạn gán hàm thực. TypeScript sẽ suy ra tất cả các kiểu hoàn toàn dựa trên kiểu hàm mà bạn đã tạo trước đó.

// Create function type for function subtract:
let subtract: (a: number, b: number) => number

// These types are redundant:
subtract = function (a: number, b: number) {
  return a - b
}

Có một cách khác để đạt được điều này. Bạn cũng có thể tạo một kiểu hàm trong khi gán hàm. Điều này cho phép bạn kết hợp cả hai bước thành một.

// Create function with function:
let subtract: (a: number, b: number) => number = function (a: number, b: number) {
  return a - b
}

Các kiểu chức năng với các kiểu và giao diện

Những cách tạo kiểu hàm mà chúng ta vừa thảo luận có một nhược điểm. Chúng không thực sự có thể tái sử dụng được. Bạn tạo một kiểu chức năng, bạn gán cho nó một chức năng và bạn đã hoàn tất. Bạn không thể sử dụng lại loại đó cho một chức năng khác, trừ khi bạn sao chép mã. May mắn thay, có một cách khác, thực sự là hai.

Bạn cũng có thể tạo các kiểu chức năng với các kiểu và giao diện . Lợi ích của cả hai là khả năng tái sử dụng đã được đề cập. Loại và giao diện sẽ không ngừng tồn tại sau khi bạn sử dụng chúng. Khi bạn tạo kiểu hàm với một kiểu hoặc giao diện, bạn có thể sử dụng nó bất cứ khi nào bạn muốn và bao nhiêu lần tùy ý.

Cú pháp cho kiểu để khai báo một kiểu hàm rất giống với cú pháp bạn đã thấy ở trên. Chỉ có hai điểm khác biệt. Đầu tiên, bạn sẽ thay thế từ khóa biến bằng typetừ khóa. Thứ hai, bạn sẽ thay thế dấu hai chấm sau tên biến bằng dấu bằng. Về cơ bản, bạn đang tạo một kiểu mới và gán cho nó một chữ ký hàm.

Khi bạn muốn sử dụng kiểu mới, bạn sử dụng nó cùng với dấu hai chấm, khi bạn tạo biểu thức hàm mới .

// Function type with variable:
let subtract: (a: number, b: number) => number

// Function type with type:
type TakeNumsReturnNums = (a: number, b: number) => number

// Use the "TakeNumsReturnNums" type with function expression:
const subtract: TakeNumsReturnNums = (a, b) => a - b

// This will work in TypeScript:
subtract(97, 13)
// Output:
// 84

// This will not work in TypeScript:
subtract(55, '15')
// TS error: Argument of type 'string' is not assignable to parameter of type 'number'.


// Use the type again:
const sumNumbers: TakeNumsReturnNums = (x, y) => x + y

// And again:
const divideNumbers: TakeNumsReturnNums = (c, d) => c / d

Làm tương tự với một giao diện yêu cầu cú pháp khác nhau. Bạn tạo một giao diện mới. Bên trong nó, bạn sẽ chỉ định các kiểu cho danh sách tham số làm khóa và kiểu trả về là giá trị. Sau đó, bạn sử dụng nó theo cách tương tự như kiểu.

// Create interface for subtract function:
interface TakeNumsReturnNums {
  // Syntax:
  // (types for parameter list): return type;
  (a: number, b: number): number;
}

// Use the "TakeNumsReturnNums" interface with function expression:
const subtract: TakeNumsReturnNums = (a, b) => a - b

// This will work in TypeScript:
subtract(55, 21)
// Output:
// 34

// This will not work in TypeScript:
subtract(true, 66)
// TS error: Argument of type 'boolean' is not assignable to parameter of type 'number'.

// Use the type again:
const sumNumbers: TakeNumsReturnNums = (x, y) => x + y

// And again:
const divideNumbers: TakeNumsReturnNums = (c, d) => c / d

Kết luận:

TypeScript giúp bạn dễ dàng viết các hàm được nhập an toàn và dễ đoán hơn. Tôi hy vọng rằng hướng dẫn này đã giúp bạn hiểu cách sử dụng các hàm trong TypeScript. Cách xác định kiểu cho tham số và kiểu trả về và cách tạo kiểu hàm.

CODE VN

CODE VN

1645667940

Cách Sử Dụng Các giao diện trong TypeScript

Các giao diện trong TypeScript: Chúng là gì và chúng ta sử dụng chúng như thế nào

Giao diện TypeScript cung cấp một cách dễ dàng để chú thích các đối tượng, lớp và chức năng. Tìm hiểu giao diện là gì và cách sử dụng chúng.

TypeScript mang lại nhiều cải tiến hữu ích cho ngôn ngữ JavaScript. Một trong số đó là hệ thống gõ tĩnh có thể giúp bạn viết mã an toàn. Các giao diện là một phần của hệ thống gõ này. Hướng dẫn này sẽ giúp bạn hiểu giao diện TypeScript là gì và cách sử dụng chúng.

JavaScript, các đối tượng và thiên nga đen

Trong JavaScript và các nơi khác, các đối tượng là một trong những cách phổ biến nhất để nhóm các dữ liệu có liên quan lại với nhau và chuyển chúng đi khắp nơi. Vấn đề là, không có cách nào trong JavaScript để chỉ định đối tượng nhất định trông như thế nào. Không có cách nào để nói đối tượng nên có thuộc tính nào hoặc giá trị của chúng phải là gì.

Điều này làm cho nó dễ dàng tạo ra mã dễ bị lỗi. Ví dụ, để tạo một đối tượng và quên thêm một số thuộc tính. Sau đó, khi đến thời điểm cuối cùng sử dụng đối tượng đó, mã của bạn sẽ bị lỗi và chương trình sẽ bị treo. Lý do? Chương trình của bạn mong đợi thuộc tính cụ thể bị thiếu.

Vấn đề có thể không phải là một tài sản bị thiếu. Có thể loại giá trị của một số thuộc tính khác với những gì chương trình của bạn mong đợi. Kết quả thường giống nhau. Mã lỗi và chương trình bị treo. Người ta có thể lập luận rằng điều này không có khả năng xảy ra. Chà, động đất và lũ lụt cũng không có khả năng xảy ra.

Vấn đề là, không ai quan tâm đến xác suất khi những sự kiện này, những con thiên nga đen này , xảy ra. Người dùng của bạn sẽ không quan tâm rằng không đúng loại hoặc thiếu thuộc tính có thể không xảy ra khi ứng dụng họ đang sử dụng gặp sự cố. Giá như có một cách để tránh điều này. Có thể, TypeScript có thể giúp bạn ở đây.

Giao diện TypeScript trở nên đơn giản

Tính năng chính của TypeScript là hệ thống kiểu mạnh mẽ của nó. Hệ thống kiểu này cho phép bạn nhanh chóng chỉ định kiểu dữ liệu nguyên thủy cho các biến. Những kiểu đơn giản này chỉ là một phần của hệ thống kiểu này. TypeScript cũng cho phép bạn làm điều này với các đối tượng. Với sự trợ giúp của TypeScript, bạn có thể xác định hình dạng của bất kỳ đối tượng nào.

Hình dạng của một đối tượng chỉ định những thuộc tính mà một đối tượng nhất định chứa. Điều này cũng bao gồm các loại của chúng, loại nào nên giá trị của các thuộc tính này. Trong TypeScript, bạn có thể chỉ định hình dạng này thông qua giao diện. Giao diện TypeScript là các kiểu trừu tượng. Các giao diện nói với trình biên dịch hai điều quan trọng.

Đầu tiên, các giao diện cho biết những thuộc tính mà một đối tượng nhất định có thể có hoặc phải có. Điều này có nghĩa là khi một số thuộc tính là tùy chọn, TypeScript sẽ biết rằng những thuộc tính này là không bắt buộc và sẽ không yêu cầu bạn xác định chúng. Thứ hai, các giao diện chỉ định kiểu của các thuộc tính này, kiểu giá trị của chúng.

Với thông tin này, TypeScript có thể cảnh báo bạn khi bạn vô tình xác định một số thuộc tính đối tượng và sử dụng sai kiểu. TypeScript sẽ biết loại nào được mong đợi sẽ được sử dụng cho mỗi thuộc tính đối tượng. Nếu bạn sử dụng loại khác, TypeScript sẽ cho bạn biết về sự không khớp, nơi nó xảy ra và cũng như cách khắc phục nó.

Tạo giao diện

Khi bạn muốn tạo một giao diện mới, bạn thực hiện bằng cách sử dụng interfacetừ khóa. Từ khóa này được theo sau bởi tên của giao diện thêm dấu ngoặc nhọn. Các dấu ngoặc này chứa hình dạng của một đối tượng, các thuộc tính và kiểu của nó. Bạn chỉ định các thuộc tính và kiểu này dưới dạng cặp khóa: giá trị.

Điều này rất giống với việc tạo đối tượng mới theo nghĩa đen . Tuy nhiên, có một số khác biệt. Đầu tiên, không có dấu bằng giữa tên của giao diện và dấu ngoặc nhọn. Thứ hai, các cặp khóa: giá trị được phân tách bằng dấu chấm phẩy. Dưới đây là các ví dụ về giao diện TypeScript đơn giản.

// Create an empty interface:
interface EmptyObject {}

// Create interface Cat:
interface Cat {
  name: string;
  age: number;
  hairColor: string;
  weight: number;
  height: number;
}

// Create interface Car:
interface Car {
  model: string;
  manufacturer: string;
  numberOfWheels: number;
  type: string;
}

// Create interface User:
interface User {
  username: string;
  password: string;
  email: string;
  isActive: boolean;
  role: 'admin' | 'user' | 'guest';
}

Giao Catdiện xác định một đối tượng có năm thuộc tính : name,, và . Tất cả các thuộc tính này là bắt buộc. Giá trị của và phải là chuỗi. Phần còn lại phải là số. Giao diện xác định một đối tượng có bốn thuộc tính :, và .agehairColorweightheightnamehairColorCarmodelmanufacturernumberOfWheelstype

Các thuộc tính này cũng là bắt buộc. Giá trị của numberOfWheelsphải là một số. Phần còn lại phải là chuỗi. Cuối cùng, Usergiao diện xác định một đối tượng có lại năm thuộc tính : username,, và . Giá trị của ba giá trị đầu tiên phải là chuỗi.passwordemailisActiverole

Giá trị của thuộc isActivetính phải là boolean, đúng hoặc sai. Giá trị của rolelà cụ thể hơn. Nó nói rằng giá trị phải là một trong ba chuỗi sau 'admin': 'user'hoặc 'guest'. Nếu bạn sử dụng bất kỳ chuỗi nào khác, TypeScript sẽ cảnh báo bạn rằng giá trị bạn sử dụng là sai, mặc dù kiểu là giống nhau.

Giao diện ngầm định

Giao diện TypeScript không nhất thiết phải do bạn tạo ra một cách rõ ràng. TypeScript cũng sẽ tự tạo giao diện khi bạn xác định một đối tượng. TypeScript sẽ xem xét các thuộc tính của đối tượng đó và giá trị của các thuộc tính này. Sau đó, nó sẽ suy ra các kiểu cụ thể bằng cách sử dụng suy luận kiểu.

Kết quả sẽ là giao diện ngầm phù hợp với đối tượng bạn vừa tạo. Điều này cũng áp dụng nếu bạn tạo đối tượng rỗng, không có bất kỳ thuộc tính nào. TypeScript sẽ chỉ tạo một giao diện trống. Điều này sau đó có thể gây ra sự cố khi bạn cố gắng thêm các thuộc tính vì TypeScript sẽ mong đợi đối tượng là và vẫn trống.

Một cách đơn giản để tránh điều này là tự bạn xác định các giao diện một cách rõ ràng. Nếu bạn tạo một đối tượng trống cũng tạo một giao diện cho nó. Giao diện này sẽ không chỉ định hình dạng hiện tại của đối tượng mà là hình dạng của nó trong tương lai. Điều này sẽ cho TypeScript biết những thuộc tính và kiểu nào được mong đợi.

Sử dụng giao diện

Khi bạn tạo một giao diện, bạn cũng phải cho TypeScript biết bạn định sử dụng nó cho đối tượng nào. Làm như vậy là dễ dàng. Khi bạn gán một đối tượng cho một biến, bạn có thể chỉ định giao diện của nó bằng cách thêm dấu hai chấm và tên của giao diện giữa tên biến và dấu bằng.

// Create an interface User:
interface User {
  password: string;
  email: string;
  role: 'admin' | 'user' | 'guest';
  logUserData: () => string;
}

// Use interface to annotate an object:
const userJoe: User = {
  password: 'some_secret_password123645',
  email: 'joe@user.co',
  role: 'user',
  logUserData: () => `${email}, ${role}`
}

Điều này cũng áp dụng ở những nơi khác. Nếu bạn muốn sử dụng một giao diện cho một đối tượng được sử dụng làm tham số hàm, bạn sử dụng cách tiếp cận tương tự. Bạn chỉ định tham số, sau đó thêm dấu hai chấm, rồi bạn chỉ định giao diện.

// Create an interface User:
interface User {
  password: string;
  email: string;
  role: 'admin' | 'user' | 'guest';
  logUserData: () => string;
}

// Create a function with "user" parameter
// and annotate the "user" parameter with "User" interface.
function getUserEmail(user: User) {
  return user.email
}

Triển khai giao diện với các lớp

TypeScript cũng cho phép bạn sử dụng giao diện với các lớp JavaScript . Tuy nhiên, với các lớp, việc triển khai hơi khác một chút. Bạn vẫn chỉ định giao diện sau tên, tên lớp trong trường hợp này. Tuy nhiên, bạn không đặt dấu hai chấm giữa tên của lớp và giao diện.

Thay vào đó, những gì bạn làm về cơ bản là thay thế các dấu hai chấm đó bằng implementstừ khóa. Điều này sẽ cho TypeScript biết rằng một lớp nhất định nên sử dụng một giao diện theo sau từ khóa này.

// Create interface Person:
interface Person {
  // Define some class properties
  // of type string and number:
  firstName: string;
  lastName: string;
  age: number;
  gender: 'male' | 'female';
  // Define class method that returns a string:
  sayHello: () => string;
}

// Annotate class "Female" with "Person" interface:
class Female implements Person {
  // Define required public properties:
  firstName: string
  lastName: string
  age: number
  gender: 'male' | 'female'

  // Create constructor and assign existing properties:
  constructor(firstName: string, lastName: string, age: number, gender: 'male' | 'female') {
    this.firstName = firstName
    this.lastName = lastName
    this.age = age
    this.gender = gender
  }

  // Define required class method:
  sayHello() {
    return `Hello, my name is ${this.firstName}.`
  }
}

Chỉ định các thuộc tính tùy chọn

Cho đến nay, tất cả các ví dụ chúng tôi đang sử dụng chỉ sử dụng các thuộc tính bắt buộc. Điều này sẽ hiệu quả đối với nhiều trường hợp. Tuy nhiên, nó có thể xảy ra rằng bạn có thể không cần một số thuộc tính trong một đối tượng nhất định mọi lúc. Một điều bạn có thể làm là tạo một giao diện mới, không có các thuộc tính tùy chọn. Sau đó, bạn có thể chuyển đổi giữa các giao diện này khi cần.

Điều này sẽ hiệu quả, nhưng nó cũng sẽ dẫn đến trùng lặp và nhiều mã hơn để duy trì. Có một điều khác bạn có thể làm. Bạn có thể lấy giao diện ban đầu và đánh dấu các thuộc tính tùy chọn là tùy chọn. Bạn đạt được điều này bằng cách đặt dấu chấm hỏi ( ?) giữa tên thuộc tính và dấu hai chấm.

// Create an interface with optional properties:
interface Person {
  firstName: string;
  lastName: string;
  middleName?: string; // <= This property will be optional
}

// This will work:
const bill: Person = {
  firstName: 'Bill',
  lastName: 'Doherty',
  middleName: 'Stevens'
}

// This will also work because "middleName"
// property is not required:
const will: Person = {
  firstName: 'William',
  lastName: 'Connors',
}

// This will not work because "lastName"
// property is required but missing:
const jack: Person = {
  firstName: 'Jack',
  middleName: 'O\'Conor',
}
// TS error: Property 'lastName' is missing in type '{ firstName: string; middleName: string; }' but required in type 'Person'.

Chỉ định thuộc tính chỉ đọc

Khi bạn tạo một đối tượng, bạn có thể muốn ngăn một số thuộc tính bị thay đổi. Bạn cũng có thể chỉ định ý định này thông qua các giao diện TypeScript. Bạn đạt được điều này bằng cách đặt readonlytừ khóa trước tên tài sản. Điều này sẽ cho TypeScript biết rằng thuộc tính theo sau là thuộc tính chỉ đọc.

Nếu bạn sử dụng giao diện để chú thích một số đối tượng, bạn sẽ có thể đặt giá trị cho thuộc tính chỉ đọc trong quá trình khởi tạo. Nếu bạn cố gắng thay đổi giá trị thuộc tính sau đó, trình biên dịch TypeScript sẽ báo lỗi.

// Create interface with read-only property:
interface User {
  username: string;
  password: string;
  readonly email: string; // <= This property will be read-only
}

// Annotate object "userFrank" with "User" interface:
const userFrank: User = {
  username: 'frankie',
  password: '123456782',
  email: 'frankie@frank.com'
}

// Try to change value of "username" property:
userFrank.username = 'frankman'

// Try to change value of "email" property:
userFrank.email = 'frankman@frank.com'
// TS error: Cannot assign to 'email' because it is a read-only property.

Giao diện cho các chức năng

Các đối tượng, bao gồm cả các lớp, không phải là những thứ duy nhất có thể sử dụng giao diện. Bạn cũng có thể sử dụng giao diện TypeScript để chú thích các chức năng. Bạn có thể làm điều này bằng cách cung cấp cho giao diện một chữ ký cuộc gọi. Điều này có nghĩa là bạn sẽ chỉ xác định danh sách tham số và kiểu trả về của hàm.

// Create interface for multiply function:
interface MultiplyFunc {
  // Specify only parameters and return type:
  (a: number, b: number): number;
}

// Annotate the "multiply" function
// with "MultiplyFunc" interface:
const multiply: MultiplyFunc = (a, b) => {
  return a * b
}

// Note:
// Thanks to MultiplyFunc interface TypeScript
// will know that "a" and "b" in "multiply" function
// are numbers so you don't have to type them explicitly.

Một điều về giao diện và chức năng. Tên của tham số trong giao diện không nhất thiết phải khớp với tên của tham số trong hàm thực tế. Bạn có thể sử dụng một tên cho tham số giao diện và một tên khác cho khai báo hàm. TypeScript sẽ kết nối các tham số với các loại của chúng một cách chính xác bằng cách sử dụng thứ tự của chúng.

interface MyFunc {
  // Specify only parameters and return type:
  (a: number, b: string, c: boolean): string;
}

// Annotate the "multiply" function
// with "MultiplyFunc" interface:
const myFunc: MyFunc = (a, b, c) => {
  return `a is ${a}, b is ${b}, c is ${c}`
}
// TypeScript will correctly infer "a" to be number,
// "b" to be string and "c" to be boolean.

Mở rộng giao diện

Một điều hữu ích là các giao diện cho phép mở rộng, giống như các lớp JavaScript. Giả sử bạn có một giao diện hiện có. Bạn cũng có một đối tượng, nhưng đối tượng này chứa nhiều thuộc tính hơn giao diện chỉ định. Một điều bạn có thể làm là thay đổi giao diện để phù hợp với đối tượng này.

Vấn đề là điều này sẽ ảnh hưởng đến tất cả các đối tượng sử dụng giao diện đó. Một thứ khác là tạo giao diện mới, sao chép giao diện cũ và thêm các thuộc tính mới. Điều này sẽ làm cho mã của bạn bị trùng lặp. May mắn thay, có tùy chọn thứ ba. Bạn có thể tạo giao diện mới và mở rộng nó với giao diện gốc.

Bằng cách này, giao diện mới sẽ kế thừa tất cả các thuộc tính được xác định trong giao diện ban đầu. Phần tốt nhất? Bạn sẽ không phải sao chép một dòng mã nào. Bạn có thể mở rộng giao diện bằng cách sử dụng extendstừ khóa. Từ khóa này cho phép bạn mở rộng một giao diện chỉ với một giao diện cũng như với nhiều giao diện.

Khi bạn muốn mở rộng giao diện với nhiều giao diện, bạn phân tách chúng bằng dấu phẩy. Từ extendskhóa nằm giữa giao diện đầu tiên, giao diện bạn đang mở rộng và giao diện thứ hai, giao diện bạn đang mở rộng.

// Create "Person" interface:
interface Person {
  name: string;
}

// Create "Male" interface that extends "Person" interface:
interface Male extends Person {
  gender: 'Male';
}
// Basically translates to:
// interface Male {
//   name: string;
//   gender: 'Male';
// }

// Create "Female" interface that also extends "Person" interface:
interface Female extends Person {
  gender: 'Female';
}
// Basically translates to:
// interface Female {
//   name: string;
//   gender: 'Female';
// }

// Create "Boy" interface that extends "Person" and "Male" interfaces:
interface Boy extends Person, Male {
  age: number;
}
// Basically translates to:
// interface Boy {
//   name: string;
//   gender: 'Male';
//   age: number;
// }

// Create "Girl" interface that extends "Person" and "Female" interfaces:
interface Girl extends Person, Female {
  age: number;
}
// Basically translates to:
// interface Girl {
//   name: string;
//   gender: 'Female';
//   age: number;
// }

const stanley: Person = {
  name: 'Stanley'
}

const david: Male = {
  name: 'David',
  gender: 'Male'
}

const sarah: Female = {
  name: 'Sarah',
  gender: 'Female'
}

const andreas: Boy = {
  name: 'Andreas',
  gender: 'Male',
  age: 13
}

const victoria: Girl = {
  name: 'Victoria',
  gender: 'Female',
  age: 6
}

Tạo giao diện chung

Một điều nữa. TypeScript cũng cho phép tạo một thứ gọi là “giao diện chung”. Các giao diện này cho phép bạn chỉ định loại thuộc tính dựa trên một hoặc nhiều tham số mà bạn cung cấp cho giao diện khi sử dụng. Bạn có thể chỉ định các tham số này bằng cách sử dụng dấu ngoặc nhọn ( <>) như trong ví dụ bên dưới.

// Create interface for UserData:
interface UserData {
  name: string;
  email: string;
}

// Create a generic interface:
interface ApiResponse<T> {
  date: Date;
  code: number;
  payload: T[];
}

// Create function to fetch API
async function fetchAPI() {
  // Use ApiResponse "interface" and pass
  // the "UserData" interface as argument (for T argument):
  const data: ApiResponse<UserData> = await fetch('/some_api_endpoint')

  // The "ApiResponse<UserData>" basically translates to:
  // interface ApiResponse<T> {
  //   date: Date;
  //   code: number;
  //   payload: UserData[];

  //   Or:
  //   payload: [name: string; email: string;]
  // }
}

Phần kết luận: 

Giao diện TypeScript cung cấp một cách dễ dàng để chú thích các đối tượng của bạn, bao gồm các lớp và cả các hàm. Điều này có thể giúp bạn viết mã an toàn hơn và dễ bảo trì hơn. Tôi hy vọng rằng hướng dẫn này đã giúp bạn hiểu và tìm hiểu về giao diện là gì và cách sử dụng chúng trong mã của bạn.

CODE VN

CODE VN

1645664700

Cách Sử Dụng Các Giao Diện Trong TypeScript

Giao diện TypeScript cung cấp một cách dễ dàng để chú thích các đối tượng, lớp và chức năng. Tìm hiểu giao diện là gì và cách sử dụng chúng.

TypeScript mang lại nhiều cải tiến hữu ích cho ngôn ngữ JavaScript. Một trong số đó là hệ thống gõ tĩnh có thể giúp bạn viết mã an toàn. Các giao diện là một phần của hệ thống gõ này. Hướng dẫn này sẽ giúp bạn hiểu giao diện TypeScript là gì và cách sử dụng chúng.

JavaScript, các đối tượng và thiên nga đen

Trong JavaScript và các nơi khác, các đối tượng là một trong những cách phổ biến nhất để nhóm các dữ liệu có liên quan lại với nhau và chuyển chúng đi khắp nơi. Vấn đề là, không có cách nào trong JavaScript để chỉ định đối tượng nhất định trông như thế nào. Không có cách nào để nói đối tượng nên có thuộc tính nào hoặc giá trị của chúng phải là gì.

Điều này làm cho nó dễ dàng tạo ra mã dễ bị lỗi. Ví dụ, để tạo một đối tượng và quên thêm một số thuộc tính. Sau đó, khi đến thời điểm cuối cùng sử dụng đối tượng đó, mã của bạn sẽ bị lỗi và chương trình sẽ bị treo. Lý do? Chương trình của bạn mong đợi thuộc tính cụ thể bị thiếu.

Vấn đề có thể không phải là một tài sản bị thiếu. Có thể loại giá trị của một số thuộc tính khác với những gì chương trình của bạn mong đợi. Kết quả thường giống nhau. Mã lỗi và chương trình bị treo. Người ta có thể lập luận rằng điều này không có khả năng xảy ra. Chà, động đất và lũ lụt cũng không có khả năng xảy ra.

Vấn đề là, không ai quan tâm đến xác suất khi những sự kiện này, những con thiên nga đen này , xảy ra. Người dùng của bạn sẽ không quan tâm rằng không đúng loại hoặc thiếu thuộc tính có thể không xảy ra khi ứng dụng họ đang sử dụng gặp sự cố. Giá như có một cách để tránh điều này. Có thể, TypeScript có thể giúp bạn ở đây.

Giao diện TypeScript trở nên đơn giản

Tính năng chính của TypeScript là hệ thống kiểu mạnh mẽ của nó. Hệ thống kiểu này cho phép bạn nhanh chóng chỉ định kiểu dữ liệu nguyên thủy cho các biến. Những kiểu đơn giản này chỉ là một phần của hệ thống kiểu này. TypeScript cũng cho phép bạn làm điều này với các đối tượng. Với sự trợ giúp của TypeScript, bạn có thể xác định hình dạng của bất kỳ đối tượng nào.

Hình dạng của một đối tượng chỉ định những thuộc tính mà một đối tượng nhất định chứa. Điều này cũng bao gồm các loại của chúng, loại nào nên giá trị của các thuộc tính này. Trong TypeScript, bạn có thể chỉ định hình dạng này thông qua giao diện. Giao diện TypeScript là các kiểu trừu tượng. Các giao diện nói với trình biên dịch hai điều quan trọng.

Đầu tiên, các giao diện cho biết những thuộc tính mà một đối tượng nhất định có thể có hoặc phải có. Điều này có nghĩa là khi một số thuộc tính là tùy chọn, TypeScript sẽ biết rằng những thuộc tính này là không bắt buộc và sẽ không yêu cầu bạn xác định chúng. Thứ hai, các giao diện chỉ định kiểu của các thuộc tính này, kiểu giá trị của chúng.

Với thông tin này, TypeScript có thể cảnh báo bạn khi bạn vô tình xác định một số thuộc tính đối tượng và sử dụng sai kiểu. TypeScript sẽ biết loại nào được mong đợi sẽ được sử dụng cho mỗi thuộc tính đối tượng. Nếu bạn sử dụng loại khác, TypeScript sẽ cho bạn biết về sự không khớp, nơi nó xảy ra và cũng như cách khắc phục nó.

Tạo giao diện

Khi bạn muốn tạo một giao diện mới, bạn thực hiện bằng cách sử dụng interfacetừ khóa. Từ khóa này được theo sau bởi tên của giao diện thêm dấu ngoặc nhọn. Các dấu ngoặc này chứa hình dạng của một đối tượng, các thuộc tính và kiểu của nó. Bạn chỉ định các thuộc tính và kiểu này dưới dạng cặp khóa: giá trị.

Điều này rất giống với việc tạo đối tượng mới theo nghĩa đen . Tuy nhiên, có một số khác biệt. Đầu tiên, không có dấu bằng giữa tên của giao diện và dấu ngoặc nhọn. Thứ hai, các cặp khóa: giá trị được phân tách bằng dấu chấm phẩy. Dưới đây là các ví dụ về giao diện TypeScript đơn giản.

// Create an empty interface:
interface EmptyObject {}

// Create interface Cat:
interface Cat {
  name: string;
  age: number;
  hairColor: string;
  weight: number;
  height: number;
}

// Create interface Car:
interface Car {
  model: string;
  manufacturer: string;
  numberOfWheels: number;
  type: string;
}

// Create interface User:
interface User {
  username: string;
  password: string;
  email: string;
  isActive: boolean;
  role: 'admin' | 'user' | 'guest';
}

Giao Catdiện xác định một đối tượng có năm thuộc tính : name,, và . Tất cả các thuộc tính này là bắt buộc. Giá trị của và phải là chuỗi. Phần còn lại phải là số. Giao diện xác định một đối tượng có bốn thuộc tính :, và .agehairColorweightheightnamehairColorCarmodelmanufacturernumberOfWheelstype

Các thuộc tính này cũng là bắt buộc. Giá trị của numberOfWheelsphải là một số. Phần còn lại phải là chuỗi. Cuối cùng, Usergiao diện xác định một đối tượng có lại năm thuộc tính : username,, và . Giá trị của ba giá trị đầu tiên phải là chuỗi.passwordemailisActiverole

Giá trị của thuộc isActivetính phải là boolean, đúng hoặc sai. Giá trị của rolelà cụ thể hơn. Nó nói rằng giá trị phải là một trong ba chuỗi sau 'admin': 'user'hoặc 'guest'. Nếu bạn sử dụng bất kỳ chuỗi nào khác, TypeScript sẽ cảnh báo bạn rằng giá trị bạn sử dụng là sai, mặc dù kiểu là giống nhau.

Giao diện ngầm định

Giao diện TypeScript không nhất thiết phải do bạn tạo ra một cách rõ ràng. TypeScript cũng sẽ tự tạo giao diện khi bạn xác định một đối tượng. TypeScript sẽ xem xét các thuộc tính của đối tượng đó và giá trị của các thuộc tính này. Sau đó, nó sẽ suy ra các kiểu cụ thể bằng cách sử dụng suy luận kiểu.

Kết quả sẽ là giao diện ngầm phù hợp với đối tượng bạn vừa tạo. Điều này cũng áp dụng nếu bạn tạo đối tượng rỗng, không có bất kỳ thuộc tính nào. TypeScript sẽ chỉ tạo một giao diện trống. Điều này sau đó có thể gây ra sự cố khi bạn cố gắng thêm các thuộc tính vì TypeScript sẽ mong đợi đối tượng là và vẫn trống.

Một cách đơn giản để tránh điều này là tự bạn xác định các giao diện một cách rõ ràng. Nếu bạn tạo một đối tượng trống cũng tạo một giao diện cho nó. Giao diện này sẽ không chỉ định hình dạng hiện tại của đối tượng mà là hình dạng của nó trong tương lai. Điều này sẽ cho TypeScript biết những thuộc tính và kiểu nào được mong đợi.

Sử dụng giao diện

Khi bạn tạo một giao diện, bạn cũng phải cho TypeScript biết bạn định sử dụng nó cho đối tượng nào. Làm như vậy là dễ dàng. Khi bạn gán một đối tượng cho một biến, bạn có thể chỉ định giao diện của nó bằng cách thêm dấu hai chấm và tên của giao diện giữa tên biến và dấu bằng.

// Create an interface User:
interface User {
  password: string;
  email: string;
  role: 'admin' | 'user' | 'guest';
  logUserData: () => string;
}

// Use interface to annotate an object:
const userJoe: User = {
  password: 'some_secret_password123645',
  email: 'joe@user.co',
  role: 'user',
  logUserData: () => `${email}, ${role}`
}

Điều này cũng áp dụng ở những nơi khác. Nếu bạn muốn sử dụng một giao diện cho một đối tượng được sử dụng làm tham số hàm, bạn sử dụng cách tiếp cận tương tự. Bạn chỉ định tham số, sau đó thêm dấu hai chấm, rồi bạn chỉ định giao diện.

// Create an interface User:
interface User {
  password: string;
  email: string;
  role: 'admin' | 'user' | 'guest';
  logUserData: () => string;
}

// Create a function with "user" parameter
// and annotate the "user" parameter with "User" interface.
function getUserEmail(user: User) {
  return user.email
}

Triển khai giao diện với các lớp

TypeScript cũng cho phép bạn sử dụng giao diện với các lớp JavaScript . Tuy nhiên, với các lớp, việc triển khai hơi khác một chút. Bạn vẫn chỉ định giao diện sau tên, tên lớp trong trường hợp này. Tuy nhiên, bạn không đặt dấu hai chấm giữa tên của lớp và giao diện.

Thay vào đó, những gì bạn làm về cơ bản là thay thế các dấu hai chấm đó bằng implementstừ khóa. Điều này sẽ cho TypeScript biết rằng một lớp nhất định nên sử dụng một giao diện theo sau từ khóa này.

// Create interface Person:
interface Person {
  // Define some class properties
  // of type string and number:
  firstName: string;
  lastName: string;
  age: number;
  gender: 'male' | 'female';
  // Define class method that returns a string:
  sayHello: () => string;
}

// Annotate class "Female" with "Person" interface:
class Female implements Person {
  // Define required public properties:
  firstName: string
  lastName: string
  age: number
  gender: 'male' | 'female'

  // Create constructor and assign existing properties:
  constructor(firstName: string, lastName: string, age: number, gender: 'male' | 'female') {
    this.firstName = firstName
    this.lastName = lastName
    this.age = age
    this.gender = gender
  }

  // Define required class method:
  sayHello() {
    return `Hello, my name is ${this.firstName}.`
  }
}

Chỉ định các thuộc tính tùy chọn

Cho đến nay, tất cả các ví dụ chúng tôi đang sử dụng chỉ sử dụng các thuộc tính bắt buộc. Điều này sẽ hiệu quả đối với nhiều trường hợp. Tuy nhiên, nó có thể xảy ra rằng bạn có thể không cần một số thuộc tính trong một đối tượng nhất định mọi lúc. Một điều bạn có thể làm là tạo một giao diện mới, không có các thuộc tính tùy chọn. Sau đó, bạn có thể chuyển đổi giữa các giao diện này khi cần.

Điều này sẽ hiệu quả, nhưng nó cũng sẽ dẫn đến trùng lặp và nhiều mã hơn để duy trì. Có một điều khác bạn có thể làm. Bạn có thể lấy giao diện ban đầu và đánh dấu các thuộc tính tùy chọn là tùy chọn. Bạn đạt được điều này bằng cách đặt dấu chấm hỏi ( ?) giữa tên thuộc tính và dấu hai chấm.

// Create an interface with optional properties:
interface Person {
  firstName: string;
  lastName: string;
  middleName?: string; // <= This property will be optional
}

// This will work:
const bill: Person = {
  firstName: 'Bill',
  lastName: 'Doherty',
  middleName: 'Stevens'
}

// This will also work because "middleName"
// property is not required:
const will: Person = {
  firstName: 'William',
  lastName: 'Connors',
}

// This will not work because "lastName"
// property is required but missing:
const jack: Person = {
  firstName: 'Jack',
  middleName: 'O\'Conor',
}
// TS error: Property 'lastName' is missing in type '{ firstName: string; middleName: string; }' but required in type 'Person'.

Chỉ định thuộc tính chỉ đọc

Khi bạn tạo một đối tượng, bạn có thể muốn ngăn một số thuộc tính bị thay đổi. Bạn cũng có thể chỉ định ý định này thông qua các giao diện TypeScript. Bạn đạt được điều này bằng cách đặt readonlytừ khóa trước tên tài sản. Điều này sẽ cho TypeScript biết rằng thuộc tính theo sau là thuộc tính chỉ đọc.

Nếu bạn sử dụng giao diện để chú thích một số đối tượng, bạn sẽ có thể đặt giá trị cho thuộc tính chỉ đọc trong quá trình khởi tạo. Nếu bạn cố gắng thay đổi giá trị thuộc tính sau đó, trình biên dịch TypeScript sẽ báo lỗi.

// Create interface with read-only property:
interface User {
  username: string;
  password: string;
  readonly email: string; // <= This property will be read-only
}

// Annotate object "userFrank" with "User" interface:
const userFrank: User = {
  username: 'frankie',
  password: '123456782',
  email: 'frankie@frank.com'
}

// Try to change value of "username" property:
userFrank.username = 'frankman'

// Try to change value of "email" property:
userFrank.email = 'frankman@frank.com'
// TS error: Cannot assign to 'email' because it is a read-only property.

Giao diện cho các chức năng

Các đối tượng, bao gồm cả các lớp, không phải là những thứ duy nhất có thể sử dụng giao diện. Bạn cũng có thể sử dụng giao diện TypeScript để chú thích các chức năng. Bạn có thể làm điều này bằng cách cung cấp cho giao diện một chữ ký cuộc gọi. Điều này có nghĩa là bạn sẽ chỉ xác định danh sách tham số và kiểu trả về của hàm.

// Create interface for multiply function:
interface MultiplyFunc {
  // Specify only parameters and return type:
  (a: number, b: number): number;
}

// Annotate the "multiply" function
// with "MultiplyFunc" interface:
const multiply: MultiplyFunc = (a, b) => {
  return a * b
}

// Note:
// Thanks to MultiplyFunc interface TypeScript
// will know that "a" and "b" in "multiply" function
// are numbers so you don't have to type them explicitly.

Một điều về giao diện và chức năng. Tên của tham số trong giao diện không nhất thiết phải khớp với tên của tham số trong hàm thực tế. Bạn có thể sử dụng một tên cho tham số giao diện và một tên khác cho khai báo hàm. TypeScript sẽ kết nối các tham số với các loại của chúng một cách chính xác bằng cách sử dụng thứ tự của chúng.

interface MyFunc {
  // Specify only parameters and return type:
  (a: number, b: string, c: boolean): string;
}

// Annotate the "multiply" function
// with "MultiplyFunc" interface:
const myFunc: MyFunc = (a, b, c) => {
  return `a is ${a}, b is ${b}, c is ${c}`
}
// TypeScript will correctly infer "a" to be number,
// "b" to be string and "c" to be boolean.

Mở rộng giao diện

Một điều hữu ích là các giao diện cho phép mở rộng, giống như các lớp JavaScript. Giả sử bạn có một giao diện hiện có. Bạn cũng có một đối tượng, nhưng đối tượng này chứa nhiều thuộc tính hơn giao diện chỉ định. Một điều bạn có thể làm là thay đổi giao diện để phù hợp với đối tượng này.

Vấn đề là điều này sẽ ảnh hưởng đến tất cả các đối tượng sử dụng giao diện đó. Một thứ khác là tạo giao diện mới, sao chép giao diện cũ và thêm các thuộc tính mới. Điều này sẽ làm cho mã của bạn bị trùng lặp. May mắn thay, có tùy chọn thứ ba. Bạn có thể tạo giao diện mới và mở rộng nó với giao diện gốc.

Bằng cách này, giao diện mới sẽ kế thừa tất cả các thuộc tính được xác định trong giao diện ban đầu. Phần tốt nhất? Bạn sẽ không phải sao chép một dòng mã nào. Bạn có thể mở rộng giao diện bằng cách sử dụng extendstừ khóa. Từ khóa này cho phép bạn mở rộng một giao diện chỉ với một giao diện cũng như với nhiều giao diện.

Khi bạn muốn mở rộng giao diện với nhiều giao diện, bạn phân tách chúng bằng dấu phẩy. Từ extendskhóa nằm giữa giao diện đầu tiên, giao diện bạn đang mở rộng và giao diện thứ hai, giao diện bạn đang mở rộng.

// Create "Person" interface:
interface Person {
  name: string;
}

// Create "Male" interface that extends "Person" interface:
interface Male extends Person {
  gender: 'Male';
}
// Basically translates to:
// interface Male {
//   name: string;
//   gender: 'Male';
// }

// Create "Female" interface that also extends "Person" interface:
interface Female extends Person {
  gender: 'Female';
}
// Basically translates to:
// interface Female {
//   name: string;
//   gender: 'Female';
// }

// Create "Boy" interface that extends "Person" and "Male" interfaces:
interface Boy extends Person, Male {
  age: number;
}
// Basically translates to:
// interface Boy {
//   name: string;
//   gender: 'Male';
//   age: number;
// }

// Create "Girl" interface that extends "Person" and "Female" interfaces:
interface Girl extends Person, Female {
  age: number;
}
// Basically translates to:
// interface Girl {
//   name: string;
//   gender: 'Female';
//   age: number;
// }

const stanley: Person = {
  name: 'Stanley'
}

const david: Male = {
  name: 'David',
  gender: 'Male'
}

const sarah: Female = {
  name: 'Sarah',
  gender: 'Female'
}

const andreas: Boy = {
  name: 'Andreas',
  gender: 'Male',
  age: 13
}

const victoria: Girl = {
  name: 'Victoria',
  gender: 'Female',
  age: 6
}

Tạo giao diện chung

Một điều nữa. TypeScript cũng cho phép tạo một thứ gọi là “giao diện chung”. Các giao diện này cho phép bạn chỉ định loại thuộc tính dựa trên một hoặc nhiều tham số mà bạn cung cấp cho giao diện khi sử dụng. Bạn có thể chỉ định các tham số này bằng cách sử dụng dấu ngoặc nhọn ( <>) như trong ví dụ bên dưới.

// Create interface for UserData:
interface UserData {
  name: string;
  email: string;
}

// Create a generic interface:
interface ApiResponse<T> {
  date: Date;
  code: number;
  payload: T[];
}

// Create function to fetch API
async function fetchAPI() {
  // Use ApiResponse "interface" and pass
  // the "UserData" interface as argument (for T argument):
  const data: ApiResponse<UserData> = await fetch('/some_api_endpoint')

  // The "ApiResponse<UserData>" basically translates to:
  // interface ApiResponse<T> {
  //   date: Date;
  //   code: number;
  //   payload: UserData[];

  //   Or:
  //   payload: [name: string; email: string;]
  // }
}

Kết Luận: 

Giao diện TypeScript cung cấp một cách dễ dàng để chú thích các đối tượng của bạn, bao gồm các lớp và cả các hàm. Điều này có thể giúp bạn viết mã an toàn hơn và dễ bảo trì hơn. Tôi hy vọng rằng hướng dẫn này đã giúp bạn hiểu và tìm hiểu về giao diện là gì và cách sử dụng chúng trong mã của bạn.