前端开发

TypeScript语法小抄

Typescript语法备忘录。

Zee
2025-01-15
12分钟
1 个标签
TypeScript

TypeScript语法小抄

typescript
/** * TypeScript 详细学习教程 * 每个概念都对比 Java 和 Python,帮助理解 */ console.log("=== TypeScript 详细学习教程 ===\n"); // ============================================================ // 第一课:基本类型系统 - 详细对比 // ============================================================ console.log("【第一课】基本类型系统 - 与Java/Python对比"); console.log("=" .repeat(50)); /** * 1.1 字符串类型 (string) * ---------------------- * Java写法: * String name = "张三"; * String message = new String("Hello"); * * Python写法: * name = "张三" # 动态类型,运行时确定 * message = 'Hello' # 单引号双引号都可以 * * TypeScript写法: */ // TypeScript字符串 - 编译时就知道类型 let tsString: string = "张三"; // 明确指定类型 let tsInferredString = "李四"; // 类型推断,TS自动知道是string // let wrongType: string = 123; // ❌ 编译错误!不能把数字赋给字符串 // 字符串操作 - 有智能提示 console.log("字符串长度:", tsString.length); // TS知道有length属性 console.log("转大写:", tsString.toUpperCase()); // TS知道有toUpperCase方法 // console.log(tsString.toFixed(2)); // ❌ 编译错误!字符串没有toFixed方法 /** * 1.2 数字类型 (number) * --------------------- * Java写法: * int age = 25; // 整数 * double price = 99.99; // 浮点数 * long bigNumber = 1000000L; * * Python写法: * age = 25 # 整数 * price = 99.99 # 浮点数 * big_number = 1000000 # Python3整数无限大 * * TypeScript写法: */ // TypeScript只有一个number类型(包含整数和浮点数) let tsAge: number = 25; // 整数 let tsPrice: number = 99.99; // 浮点数 let tsBigNumber: number = 1_000_000; // 可以用下划线分隔,提高可读性 let tsHex: number = 0xFF; // 十六进制 let tsBinary: number = 0b1010; // 二进制 let tsOctal: number = 0o744; // 八进制 console.log(`数字类型 - 年龄: ${tsAge}, 价格: ${tsPrice}, 大数: ${tsBigNumber}`); console.log(`进制表示 - 十六进制: ${tsHex}, 二进制: ${tsBinary}, 八进制: ${tsOctal}`); /** * 1.3 布尔类型 (boolean) * ---------------------- * Java写法: * boolean isActive = true; * boolean hasPermission = false; * * Python写法: * is_active = True # 注意Python是大写的True/False * has_permission = False * * TypeScript写法: */ let tsIsActive: boolean = true; // 小写的true/false,像Java let tsHasPermission: boolean = false; // 布尔运算 let tsAndResult = tsIsActive && tsHasPermission; // 逻辑与 let tsOrResult = tsIsActive || tsHasPermission; // 逻辑或 let tsNotResult = !tsIsActive; // 逻辑非 console.log(`布尔类型 - 活跃: ${tsIsActive}, 权限: ${tsHasPermission}`); console.log(`布尔运算 - AND: ${tsAndResult}, OR: ${tsOrResult}, NOT: ${tsNotResult}`); /** * 1.4 特殊类型 * ----------- */ // null 和 undefined(Java有null,Python有None) let tsNullValue: null = null; // 像Java的null let tsUndefinedValue: undefined = undefined; // JS特有,表示未定义 // any类型 - 关闭类型检查(像Python的动态类型) let tsAnyValue: any = 42; tsAnyValue = "现在是字符串"; // 可以改变类型 tsAnyValue = true; // 再次改变类型 console.log("any类型可以是任何值:", tsAnyValue); // unknown类型 - 安全的any(TypeScript独有) let tsUnknownValue: unknown = 42; tsUnknownValue = "字符串"; // 可以赋任何值 // let testNum: number = tsUnknownValue; // ❌ 错误!需要类型检查 if (typeof tsUnknownValue === "string") { let testStr: string = tsUnknownValue; // ✅ 类型检查后才能使用 } // void类型 - 没有返回值(像Java的void) function tsPrintMessage(msg: string): void { console.log(msg); // return 123; // ❌ 错误!void函数不能返回值 } // never类型 - 永远不会有返回值(抛异常或死循环) function tsThrowError(message: string): never { throw new Error(message); } console.log("\n"); // ============================================================ // 第二课:数组和元组 - 详细对比 // ============================================================ console.log("【第二课】数组和元组类型"); console.log("=" .repeat(50)); /** * 2.1 数组类型 * ----------- * Java数组: * String[] names = {"张三", "李四"}; * int[] numbers = {1, 2, 3}; * List<String> list = new ArrayList<>(); * * Python列表: * names = ["张三", "李四"] # 可以混合类型 * numbers = [1, 2, 3] * mixed = [1, "hello", True] # Python允许混合 * * TypeScript数组: */ // 方式1:类型[] let tsNames: string[] = ["张三", "李四", "王五"]; let tsNumbers: number[] = [1, 2, 3, 4, 5]; // 方式2:Array<类型>(泛型语法,像Java) let tsNamesList: Array<string> = ["赵六", "钱七"]; let tsNumbersList: Array<number> = [6, 7, 8]; // 数组操作 - TypeScript知道类型,有智能提示 tsNames.push("新用户"); // ✅ 可以添加字符串 // tsNames.push(123); // ❌ 错误!不能添加数字 // 数组方法(类似Python的列表操作) console.log("数组长度:", tsNames.length); console.log("第一个元素:", tsNames[0]); console.log("最后一个元素:", tsNames[tsNames.length - 1]); // 高阶数组方法(类似Python的map, filter, reduce) let doubled = tsNumbers.map(n => n * 2); // 像Python的[n*2 for n in numbers] let filtered = tsNumbers.filter(n => n > 2); // 像Python的[n for n in numbers if n > 2] let sum = tsNumbers.reduce((a, b) => a + b, 0); // 像Python的sum(numbers) console.log("数组操作 - 翻倍:", doubled); console.log("数组操作 - 过滤:", filtered); console.log("数组操作 - 求和:", sum); /** * 2.2 元组类型 (Tuple) * ------------------- * Java没有元组,需要创建类: * class Pair<T, U> { * T first; U second; * } * * Python元组: * person = ("张三", 25, True) # 不可变 * name, age, active = person # 解构 * * TypeScript元组: */ // 定义元组 - 固定长度和类型的数组 let tsPerson: [string, number, boolean] = ["张三", 25, true]; // ^^^^^^^^^^^^^^^^^^^^^^^^^ 必须按顺序:字符串、数字、布尔 // 访问元组 console.log("元组第一个元素(姓名):", tsPerson[0]); // string类型 console.log("元组第二个元素(年龄):", tsPerson[1]); // number类型 console.log("元组第三个元素(状态):", tsPerson[2]); // boolean类型 // 解构赋值(像Python的元组解包) let [tuplePersonName, tuplePersonAge, tupleIsActive] = tsPerson; console.log(`解构: 姓名=${tuplePersonName}, 年龄=${tuplePersonAge}, 活跃=${tupleIsActive}`); // 可选元组元素(TypeScript 3.0+) let tsOptionalTuple: [string, number?] = ["只有名字"]; // 第二个元素可选 let tsOptionalTuple2: [string, number?] = ["有年龄", 30]; console.log("\n"); // ============================================================ // 第三课:对象和接口 - 详细对比 // ============================================================ console.log("【第三课】对象和接口"); console.log("=" .repeat(50)); /** * 3.1 对象类型 * ----------- * Java对象: * class Person { * String name; * int age; * } * Person p = new Person(); * * Python字典/对象: * person = { * "name": "张三", * "age": 25 * } * # 或用类 * class Person: * def __init__(self, name, age): * self.name = name * self.age = age * * TypeScript对象: */ // 方式1:内联对象类型(快速定义) let tsPersonObj: { name: string; age: number; email?: string } = { name: "张三", age: 25 // email是可选的,可以不写 }; // 访问属性 console.log("对象属性访问:", tsPersonObj.name); // console.log(tsPersonObj.salary); // ❌ 错误!对象没有salary属性 /** * 3.2 接口 (Interface) * ------------------- * Java接口: * public interface Animal { * String getName(); * void makeSound(); * } * * Python协议(3.8+): * from typing import Protocol * class Animal(Protocol): * def get_name(self) -> str: ... * def make_sound(self) -> None: ... * * TypeScript接口: */ // 定义接口 - 描述对象的"形状" interface IAnimal { name: string; // 属性 age: number; readonly id: number; // 只读属性(像Java的final) color?: string; // 可选属性 makeSound(): void; // 方法 move(distance: number): void; // 带参数的方法 } // 实现接口 const dog: IAnimal = { id: 1, // 必须提供id name: "旺财", // 必须提供name age: 3, // 必须提供age // color可选,可以不提供 makeSound() { console.log("汪汪汪!"); }, move(distance: number) { console.log(`狗狗跑了 ${distance} 米`); } }; dog.makeSound(); dog.move(10); // dog.id = 2; // ❌ 错误!readonly属性不能修改 /** * 3.3 接口继承 * ----------- * Java接口继承: * interface Dog extends Animal { * void wagTail(); * } * * Python多继承: * class Dog(Animal, Pet): * pass * * TypeScript接口继承: */ interface Pet { owner: string; play(): void; } // 接口可以继承多个接口(像Java 8+) interface IDog extends IAnimal, Pet { breed: string; // 狗的品种 wagTail(): void; // 狗特有的方法 } const myDog: IDog = { // Animal接口的属性 id: 2, name: "小黑", age: 2, // Pet接口的属性 owner: "小明", // Dog接口自己的属性 breed: "哈士奇", // 所有方法都要实现 makeSound() { console.log("嗷呜~"); }, move(distance) { console.log(`跑了${distance}米`); }, play() { console.log("玩飞盘"); }, wagTail() { console.log("摇尾巴"); } }; console.log(`${myDog.owner}${myDog.breed}${myDog.name}`); console.log("\n"); // ============================================================ // 第四课:类型别名和联合类型 - TypeScript独特功能 // ============================================================ console.log("【第四课】类型别名和联合类型"); console.log("=" .repeat(50)); /** * 4.1 类型别名 (Type Alias) * ------------------------ * Java需要创建类或枚举: * enum Status { PENDING, SUCCESS, ERROR } * class Point { int x; int y; } * * Python类型提示(3.5+): * from typing import Union, Literal * Status = Literal["pending", "success", "error"] * Point = tuple[int, int] * * TypeScript类型别名: */ // 给基本类型起别名(提高可读性) type UserID = number; type Username = string; type Timestamp = number; let userId: UserID = 10001; let username: Username = "admin"; let loginTime: Timestamp = Date.now(); // 给复杂类型起别名 type Point = { x: number; y: number; }; type Rectangle = { topLeft: Point; bottomRight: Point; }; const rect: Rectangle = { topLeft: { x: 0, y: 0 }, bottomRight: { x: 100, y: 100 } }; console.log("矩形坐标:", rect); /** * 4.2 联合类型 (Union Types) * ------------------------- * Java需要用继承或接口: * Object result; // 可以是String或Integer * * Python Union(3.5+): * from typing import Union * result: Union[str, int] = "hello" * result = 42 # 也可以 * * TypeScript联合类型: */ // 变量可以是多种类型之一 type StringOrNumber = string | number; let mixedValue: StringOrNumber = "开始是字符串"; mixedValue = 123; // 可以改成数字 // mixedValue = true; // ❌ 错误!不能是布尔值 // 字面量联合类型(超级精确的类型) type Direction = "up" | "down" | "left" | "right"; type HttpStatus = 200 | 404 | 500; type YesOrNo = "yes" | "no"; function move(direction: Direction): void { console.log(`向${direction}移动`); } move("up"); // ✅ 正确 // move("diagonal"); // ❌ 错误!只能是四个方向之一 // 联合类型的类型守卫 function processValue(value: string | number): void { if (typeof value === "string") { // 在这个分支中,TypeScript知道value是string console.log("字符串长度:", value.length); console.log("转大写:", value.toUpperCase()); } else { // 在这个分支中,TypeScript知道value是number console.log("数字平方:", value ** 2); console.log("保留两位小数:", value.toFixed(2)); } } processValue("Hello"); processValue(3.14159); /** * 4.3 交叉类型 (Intersection Types) * --------------------------------- * Java多接口实现: * class Person implements Serializable, Cloneable { } * * Python多继承: * class Employee(Person, Manageable): pass * * TypeScript交叉类型: */ type Person = { name: string; age: number; }; type Employee = { employeeId: number; department: string; }; // 交叉类型:同时满足多个类型(像多继承) type Manager = Person & Employee & { subordinates: string[]; }; const manager: Manager = { // 必须有Person的所有属性 name: "王经理", age: 35, // 必须有Employee的所有属性 employeeId: 1001, department: "技术部", // 必须有Manager自己的属性 subordinates: ["张三", "李四", "王五"] }; console.log("经理信息:", manager); console.log("\n"); // ============================================================ // 第五课:函数类型详解 // ============================================================ console.log("【第五课】函数类型详解"); console.log("=" .repeat(50)); /** * 5.1 函数声明和类型 * ----------------- * Java方法: * public int add(int a, int b) { * return a + b; * } * * Python函数: * def add(a: int, b: int) -> int: * return a + b * * TypeScript函数: */ // 函数声明式 function add(a: number, b: number): number { return a + b; } // 函数表达式 const subtract = function(a: number, b: number): number { return a - b; }; // 箭头函数(像Java的Lambda) const multiply = (a: number, b: number): number => a * b; // 函数类型定义 type MathOperation = (a: number, b: number) => number; const divide: MathOperation = (a, b) => a / b; console.log("加法:", add(10, 5)); console.log("减法:", subtract(10, 5)); console.log("乘法:", multiply(10, 5)); console.log("除法:", divide(10, 5)); /** * 5.2 可选参数和默认参数 * -------------------- * Java重载: * void greet(String name) { ... } * void greet(String name, String title) { ... } * * Python默认参数: * def greet(name, title=None, greeting="Hello"): * ... * * TypeScript可选和默认参数: */ function greetPerson( name: string, // 必需参数 title?: string, // 可选参数(可以不传) greeting: string = "你好" // 默认参数(有默认值) ): string { if (title) { return `${greeting}, ${title} ${name}!`; } return `${greeting}, ${name}!`; } console.log(greetPerson("小明")); // 使用默认值 console.log(greetPerson("小红", "同学")); // 传入title console.log(greetPerson("老师", "张", "早上好")); // 自定义greeting /** * 5.3 剩余参数(Rest Parameters) * ------------------------------ * Java可变参数: * void printAll(String... messages) { } * * Python可变参数: * def print_all(*messages): * ... * * TypeScript剩余参数: */ function sumAll(...numbers: number[]): number { return numbers.reduce((sum, n) => sum + n, 0); } console.log("求和:", sumAll(1, 2, 3, 4, 5)); console.log("求和:", sumAll(10, 20)); /** * 5.4 函数重载 * ----------- * Java重载(真正的重载): * String format(int value) { } * String format(double value) { } * String format(String value) { } * * Python没有重载,用默认参数或*args/**kwargs * * TypeScript重载(编译时的): */ // 重载签名 function formatValue(value: string): string; function formatValue(value: number): string; function formatValue(value: boolean): string; function formatValue(value: Date): string; // 实现签名(必须兼容所有重载) function formatValue(value: string | number | boolean | Date): string { if (typeof value === "string") { return `字符串: "${value}"`; } else if (typeof value === "number") { return `数字: ${value.toLocaleString()}`; } else if (typeof value === "boolean") { return `布尔: ${value ? "真" : "假"}`; } else if (value instanceof Date) { return `日期: ${value.toLocaleDateString()}`; } return "未知类型"; } console.log(formatValue("TypeScript")); console.log(formatValue(1234567)); console.log(formatValue(true)); console.log(formatValue(new Date())); console.log("\n"); // ============================================================ // 第六课:泛型 - 终极代码复用 // ============================================================ console.log("【第六课】泛型编程"); console.log("=" .repeat(50)); /** * 6.1 泛型函数 * ----------- * Java泛型: * public <T> T identity(T value) { * return value; * } * * Python泛型(3.5+): * from typing import TypeVar, Generic * T = TypeVar('T') * def identity(value: T) -> T: * return value * * TypeScript泛型: */ // 泛型函数 - T是类型变量 function identity<T>(value: T): T { return value; } // 使用时指定类型 const str = identity<string>("Hello"); const num = identity<number>(42); // TypeScript可以自动推断类型 const inferredStr = identity("World"); // 自动推断为string const inferredNum = identity(100); // 自动推断为number console.log("泛型恒等函数:", str, num); // 多个类型参数 function pair<T, U>(first: T, second: U): [T, U] { return [first, second]; } const myPair = pair<string, number>("年龄", 25); console.log("泛型对:", myPair); /** * 6.2 泛型接口和类型 * ----------------- */ // 泛型接口(像Java的List<T>) interface Container<T> { value: T; getValue(): T; setValue(value: T): void; } // 实现泛型接口 class Box<T> implements Container<T> { value: T; constructor(value: T) { this.value = value; } getValue(): T { return this.value; } setValue(value: T): void { this.value = value; } } const stringBox = new Box<string>("礼物"); const numberBox = new Box<number>(2024); console.log("字符串盒子:", stringBox.getValue()); console.log("数字盒子:", numberBox.getValue()); // 泛型类型别名 type Result<T> = { success: boolean; data?: T; error?: string; }; function fetchUser(): Result<{ name: string; age: number }> { return { success: true, data: { name: "张三", age: 25 } }; } const userResult = fetchUser(); if (userResult.success && userResult.data) { console.log("获取用户:", userResult.data.name); } /** * 6.3 泛型约束 * ----------- * Java有界类型: * public <T extends Comparable<T>> T max(T a, T b) * * TypeScript泛型约束: */ // 约束T必须有length属性 function logLength<T extends { length: number }>(value: T): T { console.log(`长度: ${value.length}`); return value; } logLength("Hello"); // 字符串有length logLength([1, 2, 3]); // 数组有length logLength({ length: 10 }); // 对象有length属性 // logLength(123); // ❌ 错误!数字没有length // 使用keyof约束 function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key]; } const personObj = { name: "李四", age: 30, city: "北京" }; const objPersonName = getProperty(personObj, "name"); // 返回string类型 const objPersonAge = getProperty(personObj, "age"); // 返回number类型 // const invalid = getProperty(personObj, "salary"); // ❌ 错误!personObj没有salary console.log(`获取属性: name=${objPersonName}, age=${objPersonAge}`); console.log("\n"); // ============================================================ // 第七课:类 - 面向对象编程 // ============================================================ console.log("【第七课】类和面向对象"); console.log("=" .repeat(50)); /** * 7.1 类的基本结构 * -------------- * Java类: * public class Animal { * private String name; * protected int age; * public Animal(String name) { ... } * } * * Python类: * class Animal: * def __init__(self, name): * self.name = name # 没有访问修饰符 * self._age = 0 # 约定:_开头表示protected * * TypeScript类: */ class Animal { // 属性声明和访问修饰符 public name: string; // 公开(默认) protected age: number; // 受保护(子类可访问) private _id: number; // 私有(只有本类可访问) readonly species: string; // 只读(像Java的final) // 静态属性(类级别) static totalCount: number = 0; // 构造函数 constructor(name: string, age: number, species: string) { this.name = name; this.age = age; this.species = species; this._id = ++Animal.totalCount; } // 方法 public introduce(): void { console.log(`我是${this.species},名叫${this.name}${this.age}岁`); } // Getter(像Python的@property) get id(): number { return this._id; } // Setter set animalAge(value: number) { if (value < 0) { throw new Error("年龄不能为负数"); } this.age = value; } // 静态方法 static getTotal(): number { return Animal.totalCount; } } // 创建实例 const cat = new Animal("咪咪", 2, "猫"); cat.introduce(); console.log("动物ID:", cat.id); console.log("总数量:", Animal.getTotal()); /** * 7.2 类的继承 * ----------- * Java继承: * class Dog extends Animal { } * * Python继承: * class Dog(Animal): pass * * TypeScript继承: */ class Dog extends Animal { breed: string; // 狗的品种 constructor(name: string, age: number, breed: string) { super(name, age, "狗"); // 调用父类构造函数 this.breed = breed; } // 重写父类方法 introduce(): void { super.introduce(); // 调用父类方法 console.log(`我是${this.breed}`); } // 新方法 bark(): void { console.log(`${this.name}在叫: 汪汪汪!`); } } const husky = new Dog("二哈", 3, "哈士奇"); husky.introduce(); husky.bark(); /** * 7.3 抽象类 * --------- * Java抽象类: * abstract class Shape { * abstract double getArea(); * } * * Python抽象类(ABC): * from abc import ABC, abstractmethod * class Shape(ABC): * @abstractmethod * def get_area(self): pass * * TypeScript抽象类: */ abstract class Shape { abstract getArea(): number; // 抽象方法,子类必须实现 abstract getPerimeter(): number; // 可以有具体实现 describe(): void { console.log(`面积: ${this.getArea()}, 周长: ${this.getPerimeter()}`); } } class Circle extends Shape { constructor(private radius: number) { super(); } getArea(): number { return Math.PI * this.radius ** 2; } getPerimeter(): number { return 2 * Math.PI * this.radius; } } class Square extends Shape { constructor(private side: number) { super(); } getArea(): number { return this.side ** 2; } getPerimeter(): number { return 4 * this.side; } } const circle = new Circle(5); const square = new Square(4); console.log("\n图形信息:"); circle.describe(); square.describe(); console.log("\n=== TypeScript基础学习完成 ==="); console.log("你已经掌握了TypeScript的核心概念!"); console.log("下一步:使用Next.js创建博客项目,实战中深入学习");