Chuyển đến nội dung chính

Bài 4: TypeScript & Modern JavaScript trong Node.js

TypeScript setup cho Node.js, tsx/ts-node. Type-safe configuration, path aliases. ESBuild/SWC compilation. Node.js type stripping (--experimental-strip-types). Decorators, metadata.

💻 Lập trình — Bài 4 Bài 4: TypeScript & Modern JavaScript trong Node.js

Node.js Core: Từ Cơ bản đến Nâng cao

Phần 1: Node.js Internals

xdev.asia

1. TypeScript Setup cho Node.js

pnpm add -D typescript @types/node tsx
npx tsc --init
// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2023",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "dist",
    "rootDir": "src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "declaration": true,
    "sourceMap": true,
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}

2. Node.js Type Stripping (22+)

# Chạy TypeScript trực tiếp — không cần biên dịch
node --experimental-strip-types src/app.ts

# Hạn chế: không hỗ trợ enums, namespaces, decorators
# Chỉ strip types, không transform syntax

3. tsx — TypeScript Execute

// package.json
{
  "scripts": {
    "dev": "tsx watch src/app.ts",
    "start": "node dist/app.js",
    "build": "tsc",
    "typecheck": "tsc --noEmit"
  }
}
// src/app.ts
import { createServer } from 'node:http'

interface Config {
  port: number
  host: string
}

const config: Config = {
  port: Number(process.env.PORT) || 3000,
  host: process.env.HOST || '0.0.0.0',
}

const server = createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' })
  res.end(JSON.stringify({ status: 'ok', timestamp: Date.now() }))
})

server.listen(config.port, config.host, () => {
  console.log(`Server running at http://${config.host}:${config.port}`)
})

4. Path Aliases

// src/utils/logger.ts
export function log(message: string) {
  console.log(`[${new Date().toISOString()}] ${message}`)
}

// src/app.ts — dùng alias
import { log } from '@/utils/logger'
log('Server started')
# tsx hỗ trợ paths aliases tự động
# Với tsc build, cần tsc-alias
pnpm add -D tsc-alias

5. Build với ESBuild/SWC

// build.ts
import { build } from 'esbuild'

await build({
  entryPoints: ['src/app.ts'],
  bundle: true,
  platform: 'node',
  target: 'node22',
  outdir: 'dist',
  format: 'esm',
  sourcemap: true,
  external: ['pg', 'redis'], // Không bundle native modules
})

6. Decorators (Stage 3)

// Decorators — TC39 Stage 3, Node.js native support
function log(target: any, context: ClassMethodDecoratorContext) {
  return function (this: any, ...args: any[]) {
    console.log(`Calling ${String(context.name)} with`, args)
    const result = target.apply(this, args)
    console.log(`Result:`, result)
    return result
  }
}

class Calculator {
  @log
  add(a: number, b: number) {
    return a + b
  }
}

Bài tiếp theo: File System & Path — fs/promises, file watching, atomic writes.