Typescript dành cho JS developers

Bài viết này cung cấp một cái nhìn tổng quan ngắn gọn về TypeScript, tập trung vào hệ thống kiểu dữ liệu của nó.
Typescript dành cho JS developers
Typescript dành cho JS developers

Typescript là gì?

Một phiên bản Javascript++

TypeScript là một ngôn ngữ mã nguồn mở dựa trên JavaScript, một trong những ngôn ngữ được sử dụng nhiều nhất trên thế giới. Typescript mở rộng thêm Javascript bằng cách thêm vào một số static types.

Types cung cấp một phương thức tường minh hơn để mô tả các hình thái của object, diễn giải documentation tốt hơn, thông qua đó TypeScript có thể xác định rằng code của bạn đang hoạt động chính xác hay không.

Chỉ định Types là không bắt buộc trong TypeScript. 

 

Đáng tin cậy

Tất cả code JavaScript hợp lệ cũng sẽ hợp lệ với TypeScript. Typecript không bắt lỗi kiểu dữ liệu trong lúc chạy run-time. Điều đó có nghĩa là bạn có thể viết code không mắc lỗi kiểu dữ liệu, nhưng bạn có thể sẽ gặp lỗi lúc thực thi. Bạn phải hết sức cẩn thận với dữ liệu bên ngoài thu được thông qua các ajax request, hay từ các hệ thống files, storage (localStorage, sessionStorage...).

Code TypeScript được chuyển thành code JavaScript thông qua trình biên dịch TypeScript hoặc Babel. Các mã JavaScript đã được biên dịch này sẽ clean, đơn giản, chạy ở tất cả mọi nơi cần JavaScript: trình duyệt web, Node.JS hoặc trong các ứng dụng của bạn.

 

Có thể áp dụng từ từ

Việc áp dụng TypeScript không phải là thay đổi đột ngột. Bạn có thể bắt đầu bằng cách chú thích JavaScript hiện có bằng JSDoc, sau đó chuyển dần một vài files sang TypeScript. Cứ thực hiện mọi thứ một cách từ từ cho tới khi codebase của bạn được chuyển đổi hoàn toàn.

Với tính năng chỉ định kiểu dữ liệu của TypeScript, bạn không cần phải chú thích code của mình trừ khi bạn muốn an toàn hơn ^_^.

 

TypeScript dành cho JavaScript developers

TypeScript có mối quan hệ hiếm có với JavaScript. TypeScript cung cấp tất cả các tính năng sẵn có của JavaScript cùng với một lớp bổ sung: Hệ thống định dạng kiểu dữ liệu của TypeScript.

Ví dụ: JavaScript cung cấp các kiểu dữ liệu nguyên thủy như string, number và object, nhưng nó không thể kiểm tra xem bạn đã gán chúng một cách nhất quán hay chưa. TypeScript thì có.

Điều này có nghĩa là code JavaScript đang hoạt động hiện tại của bạn cũng là code TypeScript. Lợi ích chính của TypeScript là nó có thể làm nổi bật các behaviour không mong muốn trong code, từ đó giảm nguy cơ gây ra lỗi.

Bài viết này cung cấp một cái nhìn tổng quan ngắn gọn về TypeScript, tập trung vào hệ thống kiểu dữ liệu của nó.

 

Suy đoán kiểu (Types by Inference)

TypeScript sẽ tự động tạo ra các kiểu dữ liệu tương ứng cho bạn trong nhiều trường hợp. Ví dụ: khi bạn tạo một biến và gán nó cho một giá trị cụ thể, TypeScript sẽ sử dụng giá trị của biến làm kiểu dữ liệu của nó.

let helloWorld = "Hello World"

Lúc này kiểu dữ liệu của helloWorld sẽ là string. Bạn cũng có thể viết một cách tường minh hơn như sau:

let helloWorld: string = "Hello World"

Dựa trên cách hoạt động của JavaScript, TypeScript có thể xây dựng một hệ thống chấp nhận code JavaScript nhưng có thêm types (mình hay gọi đùa là có thai haha). Điều này cung cấp một hệ thống kiểu dữ liệu mà không cần thêm các ký tự bổ sung để tạo kiểu tường minh trong code hiện tại. Đó là cách TypeScript biết rằng helloWorld là một string trong ví dụ đầu tiên.

 

Chỉ định kiểu (Defining types)

TypeScript cung cấp một cú pháp mở rộng giúp bạn có thể chỉ định chính xác kiểu dữ liệu mà bạn mong muốn.

Ví dụ: để tạo một object với suy đoán kiểu tự động bao gồm namestringidnumber, bạn có thể viết như sau:

const user = {
  name: "Hayes",
  id: 0,
}

Một cách thức xịn xò hơn là khai báo một interface:

interface User {
  name: string
  id: number
}

Sau đó, bạn có thể khai báo một object JavaScript mới, đồng thời chỉ định kiểu dữ liệu cho object này:

const user: User = {
  name: "Hayes",
  id: 0,
}

Nếu bạn cung cấp một object không phù hợp với interface bạn chỉ định, TypeScript sẽ xuất ra một cảnh báo:

const user: User = {
  username: "Hayes",
  id: 0,
}

Type '{ username: string; id: number; }' is not assignable to type 'User'. Object literal may only specify known properties, and 'username' does not exist in type 'User'.

Bạn cũng có thể khai báo kiểu dữ liệu cho các class:

interface User {
  name: string
  id: number
}

class UserAccount {
  name: string
  id: number

  constructor(name: string, id: number) {
    this.name = name
    this.id = id
  }

  function getAdminUser(): User {
    //...
  }

  function deleteUser(user: User) {
    // ...
  }
}

const user: User = new UserAccount("Murphy", 1)

Javascript hỗ trợ một số kiểu dữ liệu nguyên thủy như: boolean, bigint, null, number, string, symbol, object, và undefined. Bạn hoàn toàn có thể sử dụng các kiểu dữ liệu này khi khai báo interface. Typescript cũng hỗ trợ thêm một số kiểu mới:

  • void: chấp nhận giá trị null hoặc undefined. Thường được dùng khi khai báo một function mà không trả về giá trị nào.
  • any: cái gì cũng được. Typescript sẽ không kiểm tra kiểu dữ liệu khi gặp loại này.
  • unknown: tương tự như any,  bạn có thể gán giá trị với bất cứ kiểu dữ liệu gì. Tuy nhiên, nó có vài điểm khác biệt.

Nếu như any cho phép thực hiện bất kỳ operation nào mà không kiểm tra kiểu dữ liệu thì uknown lại gần như không cho phép thực hiện operation nào.

let myValue: unknown

myValue.bar() // Error
myValue.toString() // Error
myValue[0] // Error

Chúng ta cần sử dụng type-checking để có thể thực hiện các operation trên unknown:

let myVariable: unknow

if (typeof value === 'number') {
  myVariable++
}

if (value instanceOf Xyz) {
  myVariable.foo()
}
  • never: cái kiểu này thì hơi bựa, nó đại diện cho kiểu dữ liệu có giá trị không bao giờ xảy ra =)) (nghe hơi lùng bùng phải không ^_^). 

Ví dụ: hàm dưới đây luôn trả về một Exception, nên chẳng khi nào nó trả ra giá trị gì (vì code chạy tới đây là dừng cmnr), do đó kiểu dữ liệu ở đây sẽ là never.

let showError = (message: string): never => {
  throw new Error(message)
}

 

Tự định nghĩa kiểu dữ liệu mới

Với TypeScript, bạn có thể tạo các kiểu phức tạp bằng cách kết hợp lại các kiểu đơn giản. Có hai cách phổ biến để làm như vậy đó là UnionsGenerics.

Unions

Bạn có thể chỉ định một type mới chấp nhận giá trị là một trong một số types xác định nào đó. 

Ở ví dụ sau, bạn chỉ định một kiểu dữ liệu boolean chỉ chấp nhận 1 trong 2 giá trị là true hoặc false.

type MyBool = true | false

Một vài ví dụ khác cho bạn dễ hình dung:

type WindowStates = "open" | "closed" | "minimized"

type LockStates = "locked" | "unlocked"

type OddNumbersUnderTen = 1 | 3 | 5 | 7 | 9

Unions cũng cung cấp một cách thức để xử lý các kiểu dữ liệu khác nhau. Ví dụ, bạn có thể khai báo một function nhận giá trị là một string hoặc mảng string:

function getLength(obj: string | string[]) {
  return obj.length
}

 

Generics

Generics cung cấp các variables cho types. Một ví dụ phổ biến là array. Một array không chỉ định generics có thể chứa bất kỳ thứ gì. Một array được chỉ định generics giúp mô tả các giá trị mà array đó chứa.

type StringArray = Array<string>

type NumberArray = Array<number>

type ObjectWithNameArray = Array<{ name: string }>

Bạn cũng có thể khai báo một kiểu của riêng bạn thông qua generics

interface User {
  nane: string
  id: number
}

// UserArray là một kiểu mới, có giá trị là một mảng các User.
type UserArray = Array<User>

interface Backpack<Type> {
  add: (obj: Type) => void
  get: () => Type
}

// Đoạn code này giúp Typescript biết rằng
// có một hằng số là `backpack`, và không cần quan tâm nó được khai báo ở đâu.
declare const backpack: Backpack<string>

// object là một string, bởi vì chúng ta đã khai báo nó ở interface trên là phần biến của Backpack.
const object = backpack.get()

// Vì biến backpack là một chuỗi, bạn không thể đưa một number vào hàm add().
backpack.add(23) //Argument of type 'number' is not assignable to parameter of type 'string'.

 

Hệ thống kiểu dữ liệu có cấu trúc (Structural Type System)

Một trong những nguyên tắc cốt lõi của TypeScript là kiểm tra kiểu dữ liệu bằng cách tập trung vào hình thái (shape) mà các giá trị (values) có. Điều này được gọi là "duck typing" hay "structural typing".

Trong một hệ thống kiểu dữ liệu có cấu trúc, nếu 2 object có hình thái giống nhau thì chúng được xem là cùng type.

Ở ví dụ bên dưới, biến point được xem là thuộc kiểu Point.

interface Point {
  x: number
  y: number
}

function logPoint(p: Point) {
  console.log(`${p.x}, ${p.y}`)
}

// logs "12, 26"
const point = { x: 12, y: 26 }
logPoint(point)

Biến point tuy chưa bao giờ được khai báo là một kiểu Point nhưng TypeScript so sánh hình thái của point với hình thái của kiểu Point trong quá trình kiểm tra kiểu dữ liệu. Chúng có hình thái giống nhau, vì vậy code hợp lệ.

Việc so khớp hình thái chỉ yêu cầu một tập hợp các trường của object cần so sánh.

const point3 = { x: 12, y: 26, z: 89 }
logPoint(point3) // logs "12, 26"

const rect = { x: 33, y: 3, width: 30, height: 80 }
logPoint(rect) // logs "33, 3"

const color = { hex: "#187ABF" }
logPoint(color) //Argument of type '{ hex: string; }' is not assignable to parameter of type 'Point'. Type '{ hex: string; }' is missing the following properties from type 'Point': x, y

Một ví dụ khác sử dụng class:

class VirtualPoint {
  x: number
  y: number

  constructor(x: number, y: number) {
    this.x = x
    this.y = y
  }
}

const newVPoint = new VirtualPoint(13, 56)
logPoint(newVPoint) // logs "13, 56"

Nếu object hoặc class có tất cả các property bắt buộc, TypeScript sẽ coi chúng là cùng loại, bất kể cách thức triển khai là khác nhau hay không.

Comments

Mục lục

Bài viết nổi bật

PHP là ngôn ngữ được sử dụng rộng rãi nhất trên thế giới trong lập trình web. Nó cũng bị ghét nhất. Nhưng tại sao nhiều developer lại ghét nó đến vậy? Hôm nay chúng ta hãy cùng tìm hiểu lý do xem chúng có thuyết phục không nhé ^_^
Ở bài viết này mình sẽ hướng dẫn bạn bắt đầu xây dựng một ứng dụng HMVC với Laravel, và tận dụng sức mạnh của Composer khi quản lí modules.
Có khá nhiều bạn đã yêu cầu mình một bài viết về Repository Design Pattern. Vậy mục đích của nó là gì? Nó có thực sự cần thiết cho ứng dụng của bạn hay không? Những điểm mạnh, điểm yếu của nó là gì? Chúng ta cùng đi sâu tìm hiểu qua bài viết này nhé.
Trong quá trình làm việc với Laravel Eloquent ORM, chắc hẳn các bạn từng thực hiện khá nhiều tác vụ lặp đi lặp lại - mà bạn không hề biết Laravel đã hỗ trợ sẵn. Thông qua vài mẹo và thủ thuật nhỏ trong bài viết này, mình hi vọng sẽ giúp các bạn giảm bớt sự phức tạp khi viết code cũng như bớt nhàm chán khi thực hiện các tác vụ lặp đi lặp lại theo cách thông thường.
Như đã được thông báo vào năm 2018, React Native đã và đang được đội ngũ phát triển của Facebook nỗ lực tái kiến trúc nhằm giúp nền tảng này trở nên mạnh mẽ hơn và giải quyết một số vấn đề phổ biến mà các nhà phát triển đã gặp phải trong vài năm qua.

Related posts

Redux là một framework quản lý state dựa trên ý tưởng: tất cả các state của ứng dụng sẽ được lưu xuống một global state và sử dụng các reducer function để tương tác với chúng.
Styled-Components là một thư viện giúp bạn tổ chức và quản lý styles trong các dự án sử dụng React tuân theo đề xuất từ Facebook.
Decorators trong Typescript
1102
Các bạn dev nào từng làm Angular chắc sẽ khá quen thuộc với Decorators đúng không? Nhưng bạn thật sự đã hiểu rõ về nó hay chưa? Chúng ta hãy cùng nhau ôn bài một tí nhé ^_^
PHP là ngôn ngữ được sử dụng rộng rãi nhất trên thế giới trong lập trình web. Nó cũng bị ghét nhất. Nhưng tại sao nhiều developer lại ghét nó đến vậy? Hôm nay chúng ta hãy cùng tìm hiểu lý do xem chúng có thuyết phục không nhé ^_^
Là developer, chúng ta luôn tìm cách để tiết kiệm thời gian cho các dự án của mình. Đó là lý do tại sao các thư viện được tạo ra để giảm bớt các khó khăn khi triển khai những thứ lặp đi lặp lại. Với các frontend framework như React, việc chia sẻ chức năng chung cho các dự án khác nhau trở nên dễ dàng hơn bao giờ hết.
Snappy là một thư viện PHP cho phép tạo các thumnails, snapshots và PDF từ URL hoặc trang HTML. Tác giả Barryvdh đã viết thư viện Laravel Snappy giúp việc tích hợp với Laravel dễ dàng hơn.
Bạn có thể sử dụng tính năng kiểm tra kiểu dữ liệu của Typescript để xác định các interface cho các components, nhằm chắc chắn rằng component của bạn chỉ nhận được các thông tin đầu vào chính xác.
Hooks là một tính năng bổ sung mới từ React 16.8 trở đi. Chúng cho phép bạn sử dụng State và các tính năng khác của React mà không cần viết một class.
Giới thiệu series react
601
Một vài kiến thức cơ bản cũng như nâng cao mà mình sẽ tổng hợp lại trong quá trình làm việc cũng như self learning
JWT Tokens là một cách thức lưu trữ thông tin xác thực hiệu quả, nhưng làm cách nào để chúng ta có thể giúp chúng an toàn hơn? Có 2 cách thường dùng để lưu trữ JWT Tokens là LocalStorage và Cookies. Bây giờ chúng ta sẽ bắt đầu "mổ xẻ" các ưu - nhược điểm của mỗi loại nhé.
Flexbox toàn tập
1426
Bài viết này sẽ hướng dẫn cho bạn mọi thứ về flexbox, bao gồm tất cả các thuộc tính cho phần tử cha (flex container) và phần tử con (flex items).
Như đã được thông báo vào năm 2018, React Native đã và đang được đội ngũ phát triển của Facebook nỗ lực tái kiến trúc nhằm giúp nền tảng này trở nên mạnh mẽ hơn và giải quyết một số vấn đề phổ biến mà các nhà phát triển đã gặp phải trong vài năm qua.

Tin mới nhất

Redux là một framework quản lý state dựa trên ý tưởng: tất cả các state của ứng dụng sẽ được lưu xuống một global state và sử dụng các reducer function để tương tác với chúng.
Styled-Components là một thư viện giúp bạn tổ chức và quản lý styles trong các dự án sử dụng React tuân theo đề xuất từ Facebook.
Decorators trong Typescript
1102
Các bạn dev nào từng làm Angular chắc sẽ khá quen thuộc với Decorators đúng không? Nhưng bạn thật sự đã hiểu rõ về nó hay chưa? Chúng ta hãy cùng nhau ôn bài một tí nhé ^_^
PHP là ngôn ngữ được sử dụng rộng rãi nhất trên thế giới trong lập trình web. Nó cũng bị ghét nhất. Nhưng tại sao nhiều developer lại ghét nó đến vậy? Hôm nay chúng ta hãy cùng tìm hiểu lý do xem chúng có thuyết phục không nhé ^_^
Là developer, chúng ta luôn tìm cách để tiết kiệm thời gian cho các dự án của mình. Đó là lý do tại sao các thư viện được tạo ra để giảm bớt các khó khăn khi triển khai những thứ lặp đi lặp lại. Với các frontend framework như React, việc chia sẻ chức năng chung cho các dự án khác nhau trở nên dễ dàng hơn bao giờ hết.
Snappy là một thư viện PHP cho phép tạo các thumnails, snapshots và PDF từ URL hoặc trang HTML. Tác giả Barryvdh đã viết thư viện Laravel Snappy giúp việc tích hợp với Laravel dễ dàng hơn.
IRAC (Issue - Rule - Analysis - Conclusion) là một phương pháp phổ biến và quen thuộc với sinh viên luật và dân luật nói chung. Cá nhân mình thấy phương pháp này khá hay và hoàn toàn có thể áp dụng vào bất cứ công việc hoặc ngành nghề nào.
Bạn có thể sử dụng tính năng kiểm tra kiểu dữ liệu của Typescript để xác định các interface cho các components, nhằm chắc chắn rằng component của bạn chỉ nhận được các thông tin đầu vào chính xác.
Bài viết này cung cấp một cái nhìn tổng quan ngắn gọn về TypeScript, tập trung vào hệ thống kiểu dữ liệu của nó.
Hooks là một tính năng bổ sung mới từ React 16.8 trở đi. Chúng cho phép bạn sử dụng State và các tính năng khác của React mà không cần viết một class.
Giới thiệu series react
601
Một vài kiến thức cơ bản cũng như nâng cao mà mình sẽ tổng hợp lại trong quá trình làm việc cũng như self learning
JWT Tokens là một cách thức lưu trữ thông tin xác thực hiệu quả, nhưng làm cách nào để chúng ta có thể giúp chúng an toàn hơn? Có 2 cách thường dùng để lưu trữ JWT Tokens là LocalStorage và Cookies. Bây giờ chúng ta sẽ bắt đầu "mổ xẻ" các ưu - nhược điểm của mỗi loại nhé.
Redux là một framework quản lý state dựa trên ý tưởng: tất cả các state của ứng dụng sẽ được lưu xuống một global state và sử dụng các reducer function để tương tác với chúng.
Styled-Components là một thư viện giúp bạn tổ chức và quản lý styles trong các dự án sử dụng React tuân theo đề xuất từ Facebook.
Decorators trong Typescript
1102
Các bạn dev nào từng làm Angular chắc sẽ khá quen thuộc với Decorators đúng không? Nhưng bạn thật sự đã hiểu rõ về nó hay chưa? Chúng ta hãy cùng nhau ôn bài một tí nhé ^_^
PHP là ngôn ngữ được sử dụng rộng rãi nhất trên thế giới trong lập trình web. Nó cũng bị ghét nhất. Nhưng tại sao nhiều developer lại ghét nó đến vậy? Hôm nay chúng ta hãy cùng tìm hiểu lý do xem chúng có thuyết phục không nhé ^_^
Là developer, chúng ta luôn tìm cách để tiết kiệm thời gian cho các dự án của mình. Đó là lý do tại sao các thư viện được tạo ra để giảm bớt các khó khăn khi triển khai những thứ lặp đi lặp lại. Với các frontend framework như React, việc chia sẻ chức năng chung cho các dự án khác nhau trở nên dễ dàng hơn bao giờ hết.