Skip to content

types.ts

文件信息

  • 📄 原文件:01_types.ts
  • 🔤 语言:typescript

TypeScript 类型系统 本文件介绍 TypeScript 的基本类型和类型注解。 运行方式: npx ts-node 01_types.ts 或 tsc 01_types.ts && node 01_types.js

完整代码

typescript
/**
 * ============================================================
 *                TypeScript 类型系统
 * ============================================================
 * 本文件介绍 TypeScript 的基本类型和类型注解。
 *
 * 运行方式:
 * npx ts-node 01_types.ts
 * 或
 * tsc 01_types.ts && node 01_types.js
 * ============================================================
 */

console.log("=".repeat(60));
console.log("1. 基本类型");
console.log("=".repeat(60));

// ============================================================
//                    1. 基本类型
// ============================================================

// --- 类型注解 ---
let message: string = "Hello, TypeScript!";
let count: number = 42;
let isActive: boolean = true;

console.log("\n--- 基本类型 ---");
console.log("string:", message);
console.log("number:", count);
console.log("boolean:", isActive);

// --- 类型推断 ---
let inferred = "TypeScript 会推断这是 string";
// inferred = 123;  // 错误:不能将 number 分配给 string

// --- 特殊类型 ---
console.log("\n--- 特殊类型 ---");

// null 和 undefined
let nullValue: null = null;
let undefinedValue: undefined = undefined;

// any - 任意类型(谨慎使用)
let anyValue: any = "可以是任何值";
anyValue = 123;
anyValue = { key: "value" };
console.log("any:", anyValue);

// unknown - 安全的 any
let unknownValue: unknown = "需要类型检查才能使用";
// unknownValue.length;  // 错误:必须先检查类型
if (typeof unknownValue === "string") {
    console.log("unknown string length:", unknownValue.length);
}

// void - 无返回值
function logMessage(msg: string): void {
    console.log("void 函数:", msg);
}
logMessage("Hello");

// never - 永不返回
function throwError(msg: string): never {
    throw new Error(msg);
}

// --- 数组 ---
console.log("\n--- 数组类型 ---");
const numbers: number[] = [1, 2, 3, 4, 5];
const strings: Array<string> = ["a", "b", "c"];

console.log("number[]:", numbers);
console.log("Array<string>:", strings);

// 只读数组
const readonlyArr: readonly number[] = [1, 2, 3];
// readonlyArr.push(4);  // 错误:readonly

// --- 元组 ---
console.log("\n--- 元组 ---");
const tuple: [string, number, boolean] = ["Alice", 25, true];
console.log("tuple:", tuple);
console.log("tuple[0]:", tuple[0]);  // string
console.log("tuple[1]:", tuple[1]);  // number

// 具名元组
const namedTuple: [name: string, age: number] = ["Bob", 30];


console.log("\n" + "=".repeat(60));
console.log("2. 对象类型");
console.log("=".repeat(60));

// ============================================================
//                    2. 对象类型
// ============================================================

// --- 内联对象类型 ---
console.log("\n--- 内联对象类型 ---");
const person: {
    name: string;
    age: number;
    email?: string;  // 可选属性
} = {
    name: "Alice",
    age: 25
};
console.log("person:", person);

// --- 接口 ---
console.log("\n--- 接口 ---");

interface User {
    id: number;
    name: string;
    email?: string;
    readonly createdAt: Date;
}

const user: User = {
    id: 1,
    name: "Alice",
    createdAt: new Date()
};
console.log("user:", user);
// user.createdAt = new Date();  // 错误:readonly

// 接口继承
interface Admin extends User {
    role: string;
    permissions: string[];
}

const admin: Admin = {
    id: 2,
    name: "Bob",
    createdAt: new Date(),
    role: "super_admin",
    permissions: ["read", "write", "delete"]
};
console.log("admin:", admin);

// --- 类型别名 ---
console.log("\n--- 类型别名 ---");

type Point = {
    x: number;
    y: number;
};

type ID = string | number;

const point: Point = { x: 10, y: 20 };
const userId: ID = "abc123";
const postId: ID = 42;

console.log("point:", point);
console.log("userId:", userId);
console.log("postId:", postId);

// 类型别名 vs 接口
console.log(`
类型别名 vs 接口:
- 接口可以 extends,类型别名用 &
- 接口可以声明合并
- 类型别名可以表示联合类型、元组等
- 推荐:对象用接口,其他用类型别名
`);


console.log("\n" + "=".repeat(60));
console.log("3. 联合类型与交叉类型");
console.log("=".repeat(60));

// ============================================================
//                    3. 联合类型与交叉类型
// ============================================================

// --- 联合类型 ---
console.log("\n--- 联合类型 (|) ---");

type StringOrNumber = string | number;

function printId(id: StringOrNumber) {
    if (typeof id === "string") {
        console.log("  字符串 ID:", id.toUpperCase());
    } else {
        console.log("  数字 ID:", id);
    }
}

printId("abc");
printId(123);

// 字面量联合类型
type Direction = "up" | "down" | "left" | "right";
type HttpStatus = 200 | 201 | 400 | 404 | 500;

function move(direction: Direction) {
    console.log(`  移动: ${direction}`);
}
move("up");

// --- 交叉类型 ---
console.log("\n--- 交叉类型 (&) ---");

type HasName = { name: string };
type HasAge = { age: number };
type PersonType = HasName & HasAge;

const personWithBoth: PersonType = {
    name: "Alice",
    age: 25
};
console.log("交叉类型:", personWithBoth);

// --- 类型收窄 ---
console.log("\n--- 类型收窄 ---");

function processValue(value: string | number | null) {
    // typeof 收窄
    if (typeof value === "string") {
        return value.toUpperCase();
    }

    // 真值收窄
    if (value) {
        return value * 2;
    }

    return "null value";
}

console.log("processValue('hello'):", processValue("hello"));
console.log("processValue(21):", processValue(21));
console.log("processValue(null):", processValue(null));


console.log("\n" + "=".repeat(60));
console.log("4. 函数类型");
console.log("=".repeat(60));

// ============================================================
//                    4. 函数类型
// ============================================================

// --- 函数类型注解 ---
console.log("\n--- 函数类型 ---");

function add(a: number, b: number): number {
    return a + b;
}

const multiply: (a: number, b: number) => number = (a, b) => a * b;

console.log("add(3, 5):", add(3, 5));
console.log("multiply(3, 5):", multiply(3, 5));

// --- 可选参数和默认参数 ---
console.log("\n--- 可选和默认参数 ---");

function greet(name: string, greeting: string = "Hello", punctuation?: string): string {
    return `${greeting}, ${name}${punctuation || "!"}`;
}

console.log(greet("Alice"));
console.log(greet("Bob", "Hi"));
console.log(greet("Charlie", "Hey", "?"));

// --- 剩余参数 ---
function sum(...numbers: number[]): number {
    return numbers.reduce((a, b) => a + b, 0);
}
console.log("sum(1,2,3,4,5):", sum(1, 2, 3, 4, 5));

// --- 函数重载 ---
console.log("\n--- 函数重载 ---");

function format(value: string): string;
function format(value: number): string;
function format(value: string | number): string {
    if (typeof value === "string") {
        return value.toUpperCase();
    }
    return value.toFixed(2);
}

console.log("format('hello'):", format("hello"));
console.log("format(3.14159):", format(3.14159));

// --- 泛型函数 ---
console.log("\n--- 泛型函数 ---");

function identity<T>(value: T): T {
    return value;
}

console.log("identity<string>:", identity<string>("hello"));
console.log("identity<number>:", identity<number>(42));

// 泛型约束
function getLength<T extends { length: number }>(value: T): number {
    return value.length;
}

console.log("getLength([1,2,3]):", getLength([1, 2, 3]));
console.log("getLength('hello'):", getLength("hello"));


console.log("\n" + "=".repeat(60));
console.log("5. 类型断言与类型守卫");
console.log("=".repeat(60));

// ============================================================
//                    5. 类型断言与类型守卫
// ============================================================

// --- 类型断言 ---
console.log("\n--- 类型断言 ---");

const someValue: unknown = "hello";

// as 语法
const strLength1: number = (someValue as string).length;

// 尖括号语法(JSX 中不可用)
const strLength2: number = (<string>someValue).length;

console.log("strLength:", strLength1);

// --- 类型守卫 ---
console.log("\n--- 类型守卫 ---");

interface Cat {
    meow(): void;
}

interface Dog {
    bark(): void;
}

// 自定义类型守卫
function isCat(animal: Cat | Dog): animal is Cat {
    return "meow" in animal;
}

function makeSound(animal: Cat | Dog) {
    if (isCat(animal)) {
        animal.meow();
    } else {
        animal.bark();
    }
}

const cat: Cat = { meow: () => console.log("  喵~") };
const dog: Dog = { bark: () => console.log("  汪!") };

makeSound(cat);
makeSound(dog);

// --- 可辨识联合 ---
console.log("\n--- 可辨识联合 ---");

type Shape =
    | { kind: "circle"; radius: number }
    | { kind: "rectangle"; width: number; height: number }
    | { kind: "triangle"; base: number; height: number };

function calculateArea(shape: Shape): number {
    switch (shape.kind) {
        case "circle":
            return Math.PI * shape.radius ** 2;
        case "rectangle":
            return shape.width * shape.height;
        case "triangle":
            return (shape.base * shape.height) / 2;
    }
}

console.log("圆面积:", calculateArea({ kind: "circle", radius: 5 }));
console.log("矩形面积:", calculateArea({ kind: "rectangle", width: 4, height: 5 }));


console.log("\n【总结】");
console.log(`
基本类型:
- string, number, boolean
- null, undefined
- any(避免使用), unknown(安全版 any)
- void, never

复合类型:
- 数组: number[] 或 Array<number>
- 元组: [string, number]
- 对象: { name: string }

接口与类型别名:
- interface 用于对象
- type 用于联合、元组等

高级类型:
- 联合类型: A | B
- 交叉类型: A & B
- 字面量类型: "up" | "down"

类型安全:
- 类型守卫
- 类型断言
- 可辨识联合
`);

💬 讨论

使用 GitHub 账号登录后即可参与讨论

基于 MIT 许可发布