Typescript 核心概念

0 阅读5分钟

TS安装

npm install -g typescript
pnpm add -g typescript
tsc --version // 验证

静态类型(Static Typing)

这是 TS 最核心的特性。在 JavaScript 中,变量类型是动态的(运行时确定),而 TS 在编译阶段就会检查类型,提前发现错误。

// TS中声明变量时指定类型 
let username: string = "张三"; // 只能赋值字符串 
let age: number = 25; // 只能赋值数字 

// 如果赋值类型错误,编译阶段就会报错(无需运行代码) 
// age = "25"; // ❌ 错误:不能将类型“string”分配给类型“number”

类型注解(Type Annotation)

这是 TS 中最基础的语法,显式地为变量、函数参数、函数返回值指定类型,是实现静态类型检查的基础,你可以把它理解为 “给代码贴类型标签”。

// 变量类型注解 
let count: number = 10; // 注解count为数字类型
let isActive: boolean = true; // 注解为布尔类型

// 函数参数 + 返回值注解
function add(a: number, b: number): number {
    return a + b; 
}

// 函数返回值为对象的注解(结合对象类型)
function getUser(): { id: number; name: string } {
    return { id: 1, name: "张三" };
}

注意:类型注解是 “手动指定”,和 “类型推断”(TS 自动推导)是互补的,注解可以覆盖推断,也能在推断不明确时明确类型。

接口(Interface)

用来定义对象的形状(属性和方法),是 TS 中最常用的类型约束方式,支持扩展和可选属性。

  • 可选属性、只读属性

  • 函数类型接口

  • 接口继承

// 1. 定义对象接口(描述用户对象的结构) - 可选属性 + 只读属性
interface User {
  readonly id: number; // 只读属性,初始化后不可修改
  name: string;
  age?: number; // 可选属性(可传可不传)
}

// 使用接口约束变量类型
const user: User = {
  id: 1,
  name: "李四"
  // age可选,这里可以不写
};
// user.id = 2; // ❌ 错误:只读属性不能修改

// 2. 函数类型接口(约束函数的参数和返回值)
interface Calculate {
  (a: number, b: number): number;
}

const add: Calculate = (x, y) => x + y; // 符合接口约束
const sub: Calculate = (x, y) => x - y;

// 3. 接口继承(复用已有接口)
interface AdminUser extends User {
  role: string; // 新增管理员专属属性
}

const admin: AdminUser = { id: 2, name: "管理员", role: "super" };

我们这里定义了一个 User 接口,它有三个属性:id 数字类型、name 字符串类型、age 数字类型,后面有个问号表示可选属性,可以不提供。
接着我们创建了一个 user 对象,它的类型是 User 。如果我们尝试给 user 添加一个接口中没有定义的属性,如 address,TS就会报错。

类(Class)

TS 增强了 ES6 的 Class,添加了访问修饰符、抽象类、接口实现等面向对象特性,让类的设计更严谨。

// 1. 访问修饰符(public/protected/private)
class Person {
  public name: string; // 公有的(默认),任意地方可访问
  protected age: number; // 受保护的,仅本类和子类可访问
  private id: number; // 私有的,仅本类可访问

// constructor 是构造函数,在创建对象时调用
  constructor(name: string, age: number, id: number) {
    this.name = name;
    this.age = age;
    this.id = id;
  }

// getInfo 是一个方法,返回字符串类型
  public getInfo(): string {
    return `${this.name} - ${this.age}`;
  }
}

const person = new Person("王五", 30, 1001);
console.log(person.name); // ✅ 可访问
// console.log(person.age); // ❌ 错误:protected仅类内部/子类访问
// console.log(person.id); // ❌ 错误:private仅类内部访问

// 2. 子类继承
class Student extends Person {
  constructor(name: string, age: number, id: number) {
    super(name, age, id); // 调用父类构造函数
  }

  showAge() {
    console.log(this.age); // ✅ 子类可访问protected属性
  }
}

// 3. 抽象类(abstract):不能实例化,只能被继承,用于定义规范
abstract class Shape {
  abstract getArea(): number; // 抽象方法,子类必须实现
}

class Circle extends Shape {
  radius: number;
  constructor(radius: number) {
    super();
    this.radius = radius;
  }

  getArea(): number { // 必须实现抽象方法
    return Math.PI * this.radius **2;
  }
}

// 4. 类实现接口(implements)
interface Printable {
  print(): void;
}

class Document implements Printable {
  print(): void { // 必须实现接口的print方法
    console.log("打印文档");
  }
}

装饰器(Decorator)

装饰器是 TS 的实验性特性(需手动开启配置),本质是一个函数,用于扩展类、方法、属性、参数的行为,是 AOP(面向切面编程)的实现方式,常见于框架(如 Angular、NestJS)。 基础用法(需配置 tsconfig.json:"experimentalDecorators": true):

// 1. 类装饰器:修饰整个类
function LogClass(target: any) {
  console.log("类被装饰了:", target);
  // 可以扩展类的属性/方法
  target.prototype.version = "1.0";
}

@LogClass // 应用类装饰器
class Product {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}

const product = new Product("手机");
console.log((product as any).version); // 输出1.0

// 2. 方法装饰器:修饰类的方法
function LogMethod(
  target: any,
  methodName: string,
  descriptor: PropertyDescriptor
) {
  // 保存原方法
  const originalMethod = descriptor.value;
  // 重写方法(添加日志逻辑)
  descriptor.value = function (...args: any[]) {
    console.log(`调用方法${methodName},参数:`, args);
    return originalMethod.apply(this, args);
  };
}

class Calculator {
  @LogMethod // 应用方法装饰器
  add(a: number, b: number) {
    return a + b;
  }
}

const calc = new Calculator();
calc.add(1, 2); // 输出:调用方法add,参数:[1,2],返回3

泛型(Generics)

解决 “类型复用” 问题,让函数 / 类 / 接口支持多种类型,同时保留类型检查(创建可重用的组件,然后这些组件可以处理多种数据类型)。核心是 “类型参数化”。

// 1. 泛型函数:支持任意类型的数组,返回第一个元素
function getFirst<T>(arr: T[]): T {
  return arr[0];
}

// 使用时自动推导类型
const str = getFirst(["a", "b"]); // str类型为string
const num = getFirst([1, 2]); // num类型为number

// 2. 泛型类
class Box<T> {
  private content: T;

  constructor(content: T) {
    this.content = content;
  }

  getContent(): T {
    return this.content;
  }
}

// 实例化时指定类型
const stringBox = new Box<string>("hello");
console.log(stringBox.getContent()); // 类型为string

const numberBox = new Box<number>(123);
console.log(numberBox.getContent()); // 类型为number

// 3. 泛型接口
interface Pair<K, V> {
  key: K;
  value: V;
}

const pair: Pair<string, number> = { key: "age", value: 25 };

类型推断与类型断言

类型推断:TS 会自动推导变量类型(无需手动指定),简化代码。

let msg = "hello"; // TS自动推断msg为string类型

类型断言:告诉 TS “我比你更清楚这个值的类型”,强制指定类型(仅编译阶段有效)。

const input = document.getElementById("input") as HTMLInputElement;
// 断言input是输入框元素,可直接使用value属性
console.log(input.value);

枚举

定义一组命名的常量,让代码更易读(比如状态码、选项等)。

// 定义枚举
enum Status {
  Success = 200,
  Error = 500,
  NotFound = 404
}

// 使用枚举
console.log(Status.Success); // 输出200