Type Annotations

Primitive

TypeScript hỗ trợ các type phổ biến chẳng hạn như number hay string. Ta khai báo kiểu dữ liệu của biến thông qua cú pháp type annotation (: TypeName) tương tự như trong Python.

Ví dụ:

let num: number = 5
let str: string = "Hello world!"

Ngoài các kiểu dữ liệu primitive thì TS còn hỗ trợ cả kiểu enum như trong C/C++ hoặc C#:

enum CompassDirection {
  North,
  East,
  South,
  West,
}
enum StatusCodes {
  OK = 200,
  BadRequest = 400,
  Unauthorized,
  PaymentRequired,
  Forbidden,
  NotFound,
}
enum GamePadInput {
  Up = "UP",
  Down = "DOWN",
  Left = "LEFT",
  Right = "RIGHT",
}

Non-primitive

Đối với mảng và đối tượng:

// Array
const emptyArray: string[] = []
const names: string[] = ["John", "Jane", "Peter", "David", "Mary"]
 
// Object
const person: {
  name: string
  age: number
} = {
  name: "John",
  age: 25,
}

Đối với hàm thì kiểu của nó sẽ có dạng như sau:

function helloWorld(): () => void {
  console.log("hello world!")
}

Chúng ta cũng có thể khai báo kiểu dữ liệu cho các tham số và giá trị trả về. Ví dụ:

function greeting(name: string): string {
  return `Hi ${name}`
}

Type Inference

Khi khai báo một biến với giá trị khởi tạo, TS có thể tự suy ra kiểu dữ liệu từ giá trị đó (inference).

Chẳng hạn, hai dòng code dưới đây là tương đương nhau:

let counter = 0
let counter: number = 0

Theo một cách tương tự, nếu ta sử dụng giá trị mặc định cho tham số thì TS cũng sẽ tự suy ra kiểu dữ liệu cho tham số.

// The following function
function setCounter(max = 100) {
  // ...
}
 
// is similiar with
function setCounter(max: number = 100) {
  // ...
}

Thậm chí TS cũng có thể tự suy ra kiểu dữ liệu của kết quả trả về.

// The following function
function increment(counter: number) {
  return counter++
}
 
// is similiar with
function increment(counter: number): number {
  return counter++
}

The Best Common Type

Đối với mảng mà chứa nhiều loại dữ liệu, nó sẽ có kiểu union1. Ví dụ:

const arr = [new Date(), new RegExp("d+"), new Error("error")]

Mảng arr sẽ có kiểu là (Date | RegExp | Error)[].

Contextual Typing

Xét ví dụ sau:

document.addEventListener("click", function (event) {
  console.log(event.button) //
})

Trong ví dụ trên, TS biết rằng event có kiểu là MouseEvent bởi vì giá trị click. Nếu ta thay click thành scroll thì compiler sẽ báo lỗi.

document.addEventListener("scroll", function (event) {
  console.log(event.button) // Error: Property 'button' does not exist on type 'Event'.(2339)
})

Lý do là vì TS biết được trong trường hợp này event có kiểu là UIEvent, mà thuộc tính button không tồn tại trong kiểu này.

Type Inference Vs Type Annotations

Trong thực tế, ta nên sử dụng type inference càng nhiều càng tốt và sử dụng type annotations trong các trường hợp sau:

  • Khai báo một biến và gán giá trị cho nó sau.
  • Khi ta muốn tạo ra một biến mà giá trị của nó không thể được suy ra.
  • Khi hàm trả về kiểu any và ta muốn làm rõ giá trị trả về.

Resources

Footnotes

  1. Xem thêm Union.