kilobai.comkilobai.com
Trang chủPhần mềmGiới thiệu
Đăng nhậpĐăng ký
kilobai.comkilobai.com

Blog chia sẻ kiến thức về công nghệ và phần mềm, cập nhật những thông tin và nội dung hữu ích cho người dùng.

Giới thiệuQuy địnhBảo mậtLiên hệ
© 2026 kilobai.com
Trang chủ
Backend27 tháng 4, 20265 phút đọc106 lượt xem

Tsconfig.json – file quyết định TypeScript sẽ build code của bạn như thế nào

Tác giả: Flop Dev

Chưa có đánh giá

Đăng nhập để đánh giá bài viết

Tsconfig.json – file quyết định TypeScript sẽ build code của bạn như thế nào

Hiểu tsconfig qua NestJS — khi config không còn là “file cho có”

Bạn chạy:

nest new my-app

Nest CLI tạo ra một file:

tsconfig.json

Bạn nhìn vào… và:

  • Ừm… để đó

  • Copy sang project khác

  • Không động vào nữa

👉 Và đó là sai lầm.


Sự thật ít người nói

tsconfig.json không phải config cho TypeScript.
Nó là hợp đồng giữa compile-time và runtime.

Nó quyết định:

  • Code của bạn được biến thành JS như thế nào

  • Nest có inject dependency được không

  • Decorator có thực sự hoạt động không

  • Và… app có crash hay không


Bóc tách file tsconfig của Nest

File bạn đang dùng:

{
  "module": "commonjs",
  "target": "ES2023",
  "emitDecoratorMetadata": true,
  "experimentalDecorators": true,
  "strictNullChecks": true,
  "incremental": true
}

Nhìn nhiều, nhưng thực ra chia thành 4 nhóm:


1. Runtime shape (JS sẽ trông như nào)

"module": "commonjs",
"target": "ES2023"

👉 Đây là quyết định:

  • Node sẽ hiểu code của bạn ra sao

  • Có cần transpile xuống ES5 không

  • Có dùng require hay import


2. Type system (TS kiểm soát bạn thế nào)

"strictNullChecks": true

👉 Một dòng nhưng cứu bạn khỏi hàng đống bug:

const user: string = null // ❌

Nếu tắt:

user.length // 💥 runtime crash

3. Performance

"incremental": true

👉 TypeScript sẽ cache build → nhanh hơn đáng kể khi project lớn


4. Quan trọng nhất: Decorator system

"experimentalDecorators": true,
"emitDecoratorMetadata": true

👉 Đây là lý do NestJS tồn tại.


Cùng một đoạn code — nhưng 3 thế giới runtime khác nhau


Case: app.controller.ts (Nest generate)

import { Controller, Get } from '@nestjs/common';

@Controller()
export class AppController {
  @Get()
  getHello(): string {
    return 'Hello World';
  }
}

Trạng thái 1: FULL ON (Nest hoạt động đúng)

{
  "experimentalDecorators": true,
  "emitDecoratorMetadata": true
}

JS sau khi build

let AppController = class AppController {
  getHello() {
    return 'Hello World';
  }
};

__decorate([
  (0, common_1.Get)(),
  __metadata("design:type", Function),
  __metadata("design:paramtypes", []),
  __metadata("design:returntype", String)
], AppController.prototype, "getHello", null);

AppController = __decorate([
  (0, common_1.Controller)()
], AppController);

Điều quan trọng

__metadata("design:paramtypes", [])
__metadata("design:returntype", String)

👉 Đây là thứ Nest sẽ đọc ở runtime.


Runtime thực sự

Reflect.getMetadata("design:paramtypes", AppController)
Reflect.getMetadata("design:returntype", AppController.prototype, "getHello")

👉 Nest biết:

  • Method này return gì

  • Có param gì

  • Inject gì


Kết luận trạng thái này

👉 Mọi thứ hoạt động:

  • Service được tạo và tiêm đúng vào nơi cần

  • Controller nhận đúng instance

  • Method gọi được getHello bên trong service

  • Không có undefined / không có lỗi runtime


Trạng thái 2: Decorator có — Metadata mất

{
  "experimentalDecorators": true,
  "emitDecoratorMetadata": false
}

JS sau khi build

let AppController = class AppController {
  getHello() {
    return 'Hello World';
  }
};

__decorate([
  (0, common_1.Get)()
], AppController.prototype, "getHello", null);

AppController = __decorate([
  (0, common_1.Controller)()
], AppController);

So sánh nhanh

__metadata(...)❌ không có

Reflect đọc được type❌ undefined


Điều gì xảy ra?

Controller này:

👉 vẫn chạy được ❗

Vì:

  • @Controller, @Get chỉ cần decorator

  • Không cần type metadata


Nhưng với Dependency Injection

constructor(private service: AppService) {}

👉 Nest sẽ làm:

Reflect.getMetadata("design:paramtypes", AppController)

👉 Và nhận:

undefined

Kết quả

Nest can't resolve dependencies of the AppController (?)

Quan trọng: Service không phải “chạy sai” — nó không được tạo

Đây là điểm nhiều người hiểu sai:

❌ Không phải:

  • Service chạy lỗi

  • Inject sai

  • Method bị undefined


✅ Mà là:

Instance của service KHÔNG BAO GIỜ tồn tại


Trạng thái 3: Tắt cả decorator

{
  "experimentalDecorators": false,
  "emitDecoratorMetadata": false
}

Compile sẽ fail ngay

Decorators are not valid here.

👉 TypeScript chặn từ compile-time


Insight

  • experimentalDecorators - Cho phép syntax @

  • emitDecoratorMetadata - Cho phép runtime hiểu metadata


👉 Thiếu cái đầu:

  • ❌ Không compile được

👉 Thiếu cái sau:

  • ✔ Compile OK

  • ❌ Runtime sai


Nhưng… metadata này thực chất là gì?

  • Nó từ đâu ra?

  • Ai tạo ra?

  • Tại sao TypeScript lại biết được?


👉 Và quan trọng hơn:

Làm sao tự tạo metadata của riêng bạn?


➡️ Phần tiếp theo:

Giải phẫu reflect-metadata và cơ chế phía sau NestJS DI

#typescript#nestjs#tsconfig#decorator#dependency-injection
Flop Dev

Flop Dev

Editor tại kilobai.com

Tôi từng viết code theo kiểu “chạy được là xong”. Cho đến khi nhận ra mình không thực sự hiểu hệ thống mình đang dùng. Từ đó, tôi bắt đầu đào sâu vào bản chất. Blog này là nơi tôi ghi lại những gì tôi học được — không phải để dùng, mà để hiểu.

Bình luận (0)

Đăng nhập để bình luận và đánh giá. Chưa có tài khoản? Đăng ký

Chưa có bình luận nào. Hãy là người đầu tiên!

Nội dung