编程语言

TypeScript教程(一)环境与基础语法

TypeScript 01:环境与基础语法

1. 环境搭建

```bash
# 安装 Node.js(建议 LTS 版本,macOS 可用 brew)
brew install node
node -v && npm -v

# 新建练习项目
mkdir ts-learn && cd ts-learn
npm init -y
npm install -D typescript tsx @types/node
npx tsc --init          # 生成 tsconfig.json

# 运行 TS 文件(tsx 可直接运行,无需先编译,类似 python xxx.py)
npx tsx hello.ts

对照:npm ≈ pip,package.json ≈ pyproject.toml,node_modules/ ≈ .venv/site-packages,npx ≈ python -m。

hello.ts:

const name: string = "TypeScript";
console.log(`Hello, ${name}!`); // 模板字符串 ≈ Python 的 f-string

2. 变量与基本类型

let count: number = 10;      // 可重新赋值
const PI = 3.14;             // 常量,类型自动推断为 3.14(字面量类型)
let title = "blog";          // 推断为 string,不必每处都写类型

let isActive: boolean = true;
let nothing: null = null;
let notAssigned: undefined = undefined;
let anything: unknown = 42;  // 安全版 any,使用前必须先判断类型
Python C# TypeScript
int/float int/double number(只有一种数字)
str string string
bool bool boolean
None null null/undefined
Any object/dynamic any(避免)/unknown(推荐)

规则:默认用 const,需要重新赋值才用 let,永远不要用 var。

3. 数组、元组、对象

// 数组 ≈ list
const tags: string[] = ["python", "go"];
tags.push("ts");
const upper = tags.map(t => t.toUpperCase());        // [x.upper() for x in tags]
const longTags = tags.filter(t => t.length > 2);      // [x for x in tags if len(x) > 2]
const total = [1, 2, 3].reduce((sum, n) => sum + n, 0); // sum([1,2,3])

// 元组 ≈ tuple
const point: [number, number] = [10, 20];
const [x, y] = point;                                 // 解构 ≈ x, y = point

// 对象 ≈ dict(但更像 C# 的匿名对象)
const post = { id: 1, title: "Hello", tags: ["ts"] };
console.log(post.title, post["title"]);
const { id, title: postTitle } = post;                // 解构并重命名

// 展开运算符 ≈ Python 的 {**a, **b} 和 [*a, *b]
const updated = { ...post, title: "New Title" };
const merged = [...tags, "rust"];

4. 函数

// 普通函数
function add(a: number, b: number): number {
  return a + b;
}

// 箭头函数(最常用,≈ lambda 但可以多行)
const multiply = (a: number, b: number): number => a * b;

// 可选参数 & 默认值
function greet(name: string, greeting = "Hello", suffix?: string): string {
  return `${greeting}, ${name}${suffix ?? ""}`;
}

// 剩余参数 ≈ *args
function sum(...nums: number[]): number {
  return nums.reduce((a, b) => a + b, 0);
}

// "关键字参数":TS 没有 kwargs,惯用法是传一个对象
function createUser({ name, age = 18 }: { name: string; age?: number }) {
  return { name, age };
}
createUser({ name: "Tom" });

5. 控制流与常用运算符

for (const tag of tags) { }               // 遍历值 ≈ for tag in tags
for (const [i, tag] of tags.entries()) { } // ≈ enumerate
for (const key in post) { }                // 遍历对象 key(少用)
Object.entries(post).forEach(([k, v]) => console.log(k, v)); // ≈ dict.items()

// 严格相等:永远用 === 和 !==
if (count === 10) { }

// 空值合并 ?? 与 可选链 ?.(C# 也有)
const user: { profile?: { email?: string } } = {};
const email = user.profile?.email ?? "unknown";

坑:|| 会把 0、"" 也当成假值;需要只判断 null/undefined 时用 ??。

6. 类(与 C# 非常像)

class Account {
  private balance = 0;
  constructor(public readonly owner: string) {} // 参数属性:自动声明并赋值

  deposit(amount: number): void {
    if (amount <= 0) throw new Error("amount must be positive");
    this.balance += amount;
  }

  get current(): number {      // ≈ Python @property
    return this.balance;
  }
}

const acc = new Account("bjiang");
acc.deposit(100);
console.log(acc.current);

实际项目中,TS 更偏向「函数 + 类型」的写法,类主要用于服务对象、Page Object 等。

7. 应用场景示例:把 Python 脚本改写成 TS

需求:读取一个 CSV 格式的记账文件,按分类汇总支出。

Python 版:

from collections import defaultdict
import csv

totals = defaultdict(float)
with open("expense.csv") as f:
    for row in csv.DictReader(f):
        totals[row["category"]] += float(row["amount"])
print(dict(totals))

TypeScript 版(expense.ts):

import { readFileSync } from "node:fs";

type Expense = { date: string; category: string; amount: number };

function parseCsv(path: string): Expense[] {
  const [header, ...lines] = readFileSync(path, "utf-8").trim().split("\n");
  const keys = header.split(",");
  return lines.map(line => {
    const values = line.split(",");
    const row = Object.fromEntries(keys.map((k, i) => [k, values[i]]));
    return { date: row.date, category: row.category, amount: Number(row.amount) };
  });
}

function summarize(expenses: Expense[]): Record<string, number> {
  const totals: Record<string, number> = {};
  for (const e of expenses) {
    totals[e.category] = (totals[e.category] ?? 0) + e.amount;
  }
  return totals;
}

console.table(summarize(parseCsv("expense.csv")));

expense.csv:

date,category,amount
2026-10-01,food,35.5
2026-10-01,transport,6
2026-10-02,food,42

运行:npx tsx expense.ts

8. 练习

  1. 给 summarize 增加按月份汇总的功能,返回 Record<string, Record<string, number>>。
  2. 写一个函数 topN(expenses, n),返回金额最大的 n 条记录(提示:[...arr].sort((a, b) => b.amount - a.amount).slice(0, n))。
  3. 故意把 amount 写成字符串,观察 tsc --noEmit 报的错误。

文章评论 (0)