前端开发
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创建博客项目,实战中深入学习");