Trang chủ Kiến Thức Công Nghệ Khám Phá Cách Hoạt Động Của TypeScript Compiler
Công Nghệ

Khám Phá Cách Hoạt Động Của TypeScript Compiler

Chia sẻ
Khám Phá Cách Hoạt Động Của TypeScript Compiler
Chia sẻ

Bạn đã code Typescript một khoảng thời gian, nhưng vẫn còn mơ hồ về cách mà Typescript biên dịch sang Javascript. Bài viết này sẽ giúp bạn hiểu rõ chi tiết về từng bước trong quá trình biên dịch.

Khoá học lập trình microservices với Typescript và Express

1. Typescript Compiler là gì?

TypeScript Compiler (hay tsc ) là công cụ biên dịch code TypeScript (.ts) thành JavaScript (*.js), cùng với tệp định nghĩa kiểu dữ liệu (*.d.ts) và source maps (*.js.map), giúp mã chạy trên trình duyệt và môi trường Nodejs.

tsc high level

Ngoài ra, nếu như source của bạn gặp problems, Typescript compiler sẽ giúp bạn phát hiện và khắc phục nó.

2. Các thành phần cơ bản của compiler

2.1 Parser

Parser là bộ phân tích cú pháp, chia nhỏ mã nguồn thành các phần tử (tokens) như biến, hàm và tạo ra cây biểu diễn cú pháp AST (Abstract Syntax Tree) – mỗi nút đại diện cho thành phần mã.

2.2 Binder

Binder sẽ liên kết các thành phần như biến, hàm, lớp với định nghĩa trong source code.

Ví dụ như khi bạn khai báo biến let a = 10;, compiler sẽ nhận diện a là một thành phần cụ thể là biến, và gắn kết với a là kiểu dữ liệu number.

2.3 Type Checker

Type checker là một trong những tính năng mạnh nhất của Typescript. Type checker sẽ đảm bảo tất cả các thành phần trong code đều tuân theo quy tắc mà bạn định nghĩa.

Nếu bạn khai báo một biến với kiểu là number nhưng sau đó lại cố gắng gán cho biến đó giá trị kiểu string, type checker sẽ phát hiện và báo lỗi.

2.4 Emitter

Emitter sẽ tuần tự duyệt qua các nút của AST và phát sinh ra mã Javascript tương ứng.

Ví dụ như trong typescript: let a:number = 200; sẽ được phát sinh thành var a = 200; trong javascript.

2.5 Scanner

Scanner là bộ quét mã nguồn, phân tích mã để chuyển đổi thành tokens.

Ví dụ: let a = 200; sẽ được scanner quét thành: let, a, =, 200;

3. Quá trình hoạt động compiler

Sau khi đã hiểu hơn về các thành phần cơ bản, thì mình sẽ đề cập đến quá trình hoạt động compiler:

Các thành phần cơ bản của Typescript Compiler

Quá trình biên dịch TypeScript bắt đầu khi bạn chạy lệnh tsc. Để thực hiện, TypeScript Compiler cần file tsconfig.json:

  1. Compiler Options: phần này chứa các cấu hình cho trình biên dịch Typescript.
  2. Input Files: phần này chứa các file TypeScript cần biên dịch.

Typescript

{
	"compilerOptions": {
    	...
    },
    
    "files": [
        "src/*.ts"
    ],
}

Quá trình biên dịch sẽ được tạo ra dưới dạng đối tượng Program, được định nghĩa trong file src/compiler/program.ts.

Khi đối tượng được tạo, nó sẽ tải tất cả các input files và các tệp phụ thuộc. Sau đó, gọi Parser– được định nghĩa trong tệp src/compiler/parser.ts để phân tích từng files thành AST (Abstract Syntax Tree).

tsc program parser to ast

Trong quá trình hoạt động, Parser tạo ra đối tượng Scanner được định nghĩa trong file src/compiler/scanner.ts, nó sẽ quét qua source code và sinh ra chuỗi SyntaxKind tokens.

Sau đó, AST sẽ được truyền cho Binder được định nghĩa trong tệp src/compiler/binder.ts để tạo map giữa các nút AST và Symbols.

tsc map ast binder symbols

Một Symbol bổ sung vào metadata, để lưu trữ thông tin kiểu của mỗi nút. Binder tạo ra một symbols table, sẽ được sử dụng sau này để kiểm tra kiểu dữ liệu.

Sau đó, lệnh Program.emit được gọi, Emit Worker sẽ được tạo ra để chuyển đổi AST thành code JavaScript và các tệp khác. Có hai loại emitter:

  1. JavaScript Emitter: được định nghĩa trong src/compiler/emitter.ts, emitting source code JavaScript và source maps.
  2. Type Definition Emitter: được định nghĩa trong src/compiler/definitionEmitter.ts, emitting các file định nghĩa kiểu dữ liệu.

Khi Emitter chạy, nó sẽ gọi hàm getDiagnostics() để tạo một Type Checker, được định nghĩa trong file src/compiler/checker.ts. Sau đó, Emitter sẽ duyệt qua AST để xử lý từng nút.

Trên mỗi nút, nó sẽ phân tích mã, sử dụng dữ liệu kiểu từ Symbols Table, và nếu mọi thứ không có vấn đề, JavaScript sources cuối cùng sẽ được sinh ra.

tsc emitter

4. Báo lỗi khi Typescript Compiler

Nhiều loại lỗi khác nhau có thể được trả về trong quá trình biên dịch, phụ thuộc vào giai đoạn trình biên dịch tìm thấy lỗi.

Đây là cách các lỗi được định nghĩa và sử dụng trong hệ thống compiles:

Typescript

enum BuildResultFlags {
    None = 0,
    Success = 1 << 0,
    DeclarationOutputUnchanged = 1 << 1,
 
    ConfigFileErrors = 1 << 2,
    SyntaxErrors = 1 << 3,
    TypeErrors = 1 << 4,
    DeclarationEmitErrors = 1 << 5,
    EmitErrors = 1 << 6,
 
    AnyErrors = ConfigFileErrors | SyntaxErrors | TypeErrors | DeclarationEmitErrors | EmitErrors
}
  • Nếu có lỗi trong tệp tsconfig.json, ConfigFileErrors sẽ được trả về.
  • Nếu lỗi được Scanner tìm thấy,  SyntaxErrors được trả về.
  • Nếu code được viết đúng cú pháp, nhưng không đúng ngữ nghĩa, đa phần sẽ trả về TypeErrors.

5. Tối ưu hóa quá trình biên dịch

  • Sử dụng tsc --watch: cho phép compiler giám sát thay đổi trong source code, tự động compiles chỉ thành phần thay đổi.
  • Tối ưu cấu trúc dự án: chia dự án thành các module nhỏ hơn dễ bảo trì source code.
  • Sử dụng skipLibCheck: Khi làm việc với các thư viện bên ngoài, bạn có thể sử dụng skipLibCheck để bỏ qua kiểm tra kiểu của các file .d.ts .

6. Kết luận

Hy vọng thông qua bài viết này, bạn đã hiểu rõ quá trình chi tiết compiles.

Nếu bạn quan tâm các chủ đề khác liên quan, bạn có thể tham khảo một số bài viết dưới đây:

  • Backend cơ bản: REST API Versioning – Quản lý các Version của REST API
  • Backend cơ bản: Tìm hiểu API Gateway
  • NestJS: Giải Pháp Toàn Diện Cho Ứng Dụng Server-Side
Bài viết cùng chuyên mục
Tối ưu ứng dụng với cấu trúc dữ liệu cơ bản và bitwise
Công Nghệ

Tối ưu ứng dụng với cấu trúc dữ liệu cơ bản và bitwise

Trong bài viết này, 200Lab sẽ chia sẻ những trường hợp dễ...

Công Nghệ

So sánh Flutter vs React Native: Framework nào đáng học năm 2021

Điểm chung của Flutter, React Native đều là Cross-platform Mobile, build native...

HTTP/2 là gì? So sánh HTTP/2 và HTTP/1
Công Nghệ

HTTP/2 là gì? So sánh HTTP/2 và HTTP/1

Từ khi Internet ra đời, sự phát triển về các giao thức...

Upload File từ Frontend đến Backend mà rất nhiều bạn vẫn đang làm sai!!
Công Nghệ

Upload File từ Frontend đến Backend mà rất nhiều bạn vẫn đang làm sai!!

1. Client encode file (base64) rồi gởi về backend 200Lab đã từng...

Công Nghệ

React Native – Hướng dẫn làm việc với Polyline và Animated-Polyline trên Map

Vẽ đường đi trên bản đồ là một nghiệp vụ vô cùng...

Công Nghệ

Hybrid App và Native App: Những khác biệt to lớn

Bất cứ khi nào một công ty quyết định làm ứng dụng...

Web/System Architecture 101 – Kiến trúc web/hệ thống cơ bản cho người mới
Công Nghệ

Web/System Architecture 101 – Kiến trúc web/hệ thống cơ bản cho người mới

Đây là một kiến trúc cơ bản mà bất kì một người...

Công Nghệ

Tư duy kiến trúc thông qua các trò chơi mà rất nhiều bạn không biết

Tư duy kiến trúc là gì? Tư duy kiến trúc có thể...