Skip to content

TypeScript

一、TypeScript 基础

1. TypeScript 是什么?

TypeScript 是 JavaScript 的超集,添加了静态类型系统。

核心特性:

  • 静态类型检查:编译时发现错误
  • 类型注解:为变量、函数等添加类型
  • 接口和类型:定义数据结构
  • 泛型:支持类型参数化
  • ES6+ 支持:支持最新的 JavaScript 特性

2. 为什么使用 TypeScript?

优势:

  • 早期发现错误,减少运行时错误
  • 更好的 IDE 支持和代码提示
  • 代码更易维护和重构
  • 更好的文档性(类型即文档)

劣势:

  • 需要编译步骤
  • 学习曲线
  • 对于小项目可能过度设计

二、基本类型

1. 原始类型

typescript
// 数字
let count: number = 10;

// 字符串
let name: string = "Alice";

// 布尔值
let isActive: boolean = true;

// null 和 undefined
let data: null = null;
let value: undefined = undefined;

// Symbol
let sym: symbol = Symbol("key");

// BigInt
let big: bigint = 100n;

2. 数组和元组

typescript
// 数组
let numbers: number[] = [1, 2, 3];
let names: Array<string> = ["Alice", "Bob"];

// 元组
let tuple: [string, number] = ["Alice", 20];
tuple[0] = "Bob";
tuple[1] = 21;

// 可选元组
let optionalTuple: [string, number?] = ["Alice"];

3. 对象类型

typescript
// 对象字面量
let user: { name: string; age: number } = {
  name: "Alice",
  age: 20
};

// 可选属性
let user2: { name: string; age?: number } = {
  name: "Alice"
};

// 只读属性
let config: { readonly apiKey: string } = {
  apiKey: "123456"
};

4. 枚举(Enum)

typescript
// 数字枚举
enum Status {
  Pending,
  Approved,
  Rejected
}

let status: Status = Status.Pending;

// 字符串枚举
enum Color {
  Red = "red",
  Green = "green",
  Blue = "blue"
}

// 常量枚举(编译时内联)
const enum Direction {
  Up,
  Down,
  Left,
  Right
}

5. Any 和 Unknown

typescript
// any:任意类型,失去类型检查
let value: any = "hello";
value = 123;
value = true;

// unknown:类型安全的 any
let value2: unknown = "hello";
// value2.toUpperCase(); // 错误:需要类型检查

if (typeof value2 === "string") {
  value2.toUpperCase(); // 正确
}

6. Void 和 Never

typescript
// void:函数没有返回值
function log(message: string): void {
  console.log(message);
}

// never:函数永远不会返回
function throwError(message: string): never {
  throw new Error(message);
}

function infiniteLoop(): never {
  while (true) {}
}

三、函数类型

1. 函数声明

typescript
// 函数参数和返回值类型
function add(a: number, b: number): number {
  return a + b;
}

// 可选参数
function greet(name: string, age?: number): string {
  if (age) {
    return `Hello, ${name}, you are ${age} years old`;
  }
  return `Hello, ${name}`;
}

// 默认参数
function multiply(a: number, b: number = 1): number {
  return a * b;
}

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

2. 函数表达式

typescript
// 箭头函数
const add = (a: number, b: number): number => {
  return a + b;
};

// 函数类型
type AddFunction = (a: number, b: number) => number;

const multiply: AddFunction = (a, b) => {
  return a * b;
};

3. 函数重载

typescript
function process(value: string): string;
function process(value: number): number;
function process(value: string | number): string | number {
  if (typeof value === "string") {
    return value.toUpperCase();
  }
  return value * 2;
}

const result1 = process("hello");  // string
const result2 = process(10);       // number

四、接口和类型别名

1. 接口(Interface)

typescript
interface User {
  name: string;
  age: number;
  email?: string;  // 可选属性
  readonly id: number;  // 只读属性
}

const user: User = {
  name: "Alice",
  age: 20,
  id: 1
};

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

2. 类型别名(Type)

typescript
type User = {
  name: string;
  age: number;
};

// 联合类型
type Status = "pending" | "approved" | "rejected";

// 交叉类型
type Admin = User & {
  role: string;
};

3. Interface vs Type

相同点:

  • 都可以定义对象类型
  • 都支持扩展

不同点:

  • Interface 支持声明合并,Type 不支持
  • Type 可以定义联合类型、交叉类型等,Interface 主要用于对象
typescript
// Interface 声明合并
interface Window {
  customProperty: string;
}
interface Window {
  anotherProperty: number;
}

// Type 联合类型
type ID = string | number;
type Status = "active" | "inactive";

五、泛型

1. 泛型函数

typescript
// 泛型函数
function identity<T>(value: T): T {
  return value;
}

const result1 = identity<string>("hello");
const result2 = identity<number>(123);
const result3 = identity("hello");  // 类型推断

// 多个类型参数
function pair<T, U>(first: T, second: U): [T, U] {
  return [first, second];
}

2. 泛型接口

typescript
interface Repository<T> {
  findById(id: number): T | undefined;
  findAll(): T[];
  save(entity: T): void;
}

class UserRepository implements Repository<User> {
  findById(id: number): User | undefined {
    // ...
  }
  findAll(): User[] {
    // ...
  }
  save(entity: User): void {
    // ...
  }
}

3. 泛型类

typescript
class Container<T> {
  private value: T;
  
  constructor(value: T) {
    this.value = value;
  }
  
  getValue(): T {
    return this.value;
  }
  
  setValue(value: T): void {
    this.value = value;
  }
}

const container = new Container<string>("hello");

4. 泛型约束

typescript
// 约束类型参数必须有 length 属性
function logLength<T extends { length: number }>(value: T): void {
  console.log(value.length);
}

logLength("hello");  // 5
logLength([1, 2, 3]);  // 3

// 使用 keyof 约束
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const user = { name: "Alice", age: 20 };
const name = getProperty(user, "name");  // string

六、高级类型

1. 联合类型和交叉类型

typescript
// 联合类型
type ID = string | number;

function processId(id: ID) {
  if (typeof id === "string") {
    return id.toUpperCase();
  }
  return id.toString();
}

// 交叉类型
type Admin = User & {
  role: string;
  permissions: string[];
};

2. 类型断言

typescript
// as 语法
const value = "hello" as string;

// <类型> 语法
const element = <HTMLInputElement>document.getElementById("input");

// 非空断言
const user = users.find(u => u.id === 1)!;

3. 类型保护

typescript
// typeof 类型保护
function isString(value: unknown): value is string {
  return typeof value === "string";
}

// instanceof 类型保护
class Dog {
  bark() {}
}
class Cat {
  meow() {}
}

function isDog(animal: Dog | Cat): animal is Dog {
  return animal instanceof Dog;
}

// 自定义类型保护
interface Fish {
  swim(): void;
}
interface Bird {
  fly(): void;
}

function isFish(animal: Fish | Bird): animal is Fish {
  return (animal as Fish).swim !== undefined;
}

4. 映射类型

typescript
// Partial:所有属性变为可选
type Partial<T> = {
  [P in keyof T]?: T[P];
};

// Readonly:所有属性变为只读
type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

// Pick:选择部分属性
type Pick<T, K extends keyof T> = {
  [P in K]: T[P];
};

// Omit:排除部分属性
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

// 使用示例
type PartialUser = Partial<User>;
type ReadonlyUser = Readonly<User>;
type UserName = Pick<User, "name">;
type UserWithoutId = Omit<User, "id">;

5. 条件类型

typescript
// 条件类型
type NonNullable<T> = T extends null | undefined ? never : T;

type Example1 = NonNullable<string | null>;  // string
type Example2 = NonNullable<number | undefined>;  // number

// 分布式条件类型
type ToArray<T> = T extends any ? T[] : never;
type StrArrOrNumArr = ToArray<string | number>;  // string[] | number[]

七、类

1. 类的定义

typescript
class User {
  // 属性
  private name: string;
  public age: number;
  protected email: string;
  readonly id: number;
  
  // 构造函数
  constructor(name: string, age: number, email: string) {
    this.name = name;
    this.age = age;
    this.email = email;
    this.id = Math.random();
  }
  
  // 方法
  getName(): string {
    return this.name;
  }
  
  // 静态方法
  static createAdmin(name: string): User {
    const user = new User(name, 0, "");
    return user;
  }
}

2. 访问修饰符

  • public(默认):公共的,任何地方都可以访问
  • private:私有的,只能在类内部访问
  • protected:受保护的,可以在类内部和子类中访问
typescript
class Animal {
  public name: string;
  private age: number;
  protected species: string;
  
  constructor(name: string, age: number, species: string) {
    this.name = name;
    this.age = age;
    this.species = species;
  }
}

class Dog extends Animal {
  constructor(name: string, age: number) {
    super(name, age, "dog");
    console.log(this.species);  // 可以访问 protected
  }
}

3. 抽象类

typescript
abstract class Shape {
  abstract area(): number;
  
  getPerimeter(): number {
    return 0;
  }
}

class Circle extends Shape {
  constructor(private radius: number) {
    super();
  }
  
  area(): number {
    return Math.PI * this.radius ** 2;
  }
}

4. 接口实现

typescript
interface Flyable {
  fly(): void;
}

interface Swimmable {
  swim(): void;
}

class Duck implements Flyable, Swimmable {
  fly(): void {
    console.log("Duck is flying");
  }
  
  swim(): void {
    console.log("Duck is swimming");
  }
}

八、模块

1. 导出和导入

typescript
// 导出
export const PI = 3.14;
export function add(a: number, b: number): number {
  return a + b;
}
export class User {}

// 默认导出
export default class Admin {}

// 导入
import { PI, add, User } from "./utils";
import Admin from "./admin";
import * as Utils from "./utils";

// 重新导出
export { User } from "./user";
export * from "./types";

2. 命名空间

typescript
namespace MathUtils {
  export function add(a: number, b: number): number {
    return a + b;
  }
  
  export function multiply(a: number, b: number): number {
    return a * b;
  }
}

// 使用
MathUtils.add(1, 2);

九、工具类型

1. 常用工具类型

typescript
// Partial<T>:所有属性变为可选
type PartialUser = Partial<User>;

// Required<T>:所有属性变为必填
type RequiredUser = Required<User>;

// Readonly<T>:所有属性变为只读
type ReadonlyUser = Readonly<User>;

// Pick<T, K>:选择部分属性
type UserName = Pick<User, "name">;

// Omit<T, K>:排除部分属性
type UserWithoutId = Omit<User, "id">;

// Record<K, T>:创建记录类型
type UserMap = Record<string, User>;

// Exclude<T, U>:从 T 中排除 U
type T0 = Exclude<"a" | "b" | "c", "a">;  // "b" | "c"

// Extract<T, U>:从 T 中提取 U
type T1 = Extract<"a" | "b" | "c", "a" | "f">;  // "a"

// NonNullable<T>:排除 null 和 undefined
type T2 = NonNullable<string | null | undefined>;  // string

// ReturnType<T>:获取函数返回类型
type T3 = ReturnType<() => string>;  // string

// Parameters<T>:获取函数参数类型
type T4 = Parameters<(a: number, b: string) => void>;  // [number, string]

十、常见面试题

1. TypeScript 和 JavaScript 的区别?

特性TypeScriptJavaScript
类型系统静态类型动态类型
编译需要编译直接运行
类型检查编译时运行时
IDE 支持更好一般
学习曲线较陡平缓

2. any 和 unknown 的区别?

  • any:任意类型,失去类型检查,不推荐使用
  • unknown:类型安全的 any,需要类型检查后才能使用
typescript
let value1: any = "hello";
value1.toUpperCase();  // 可以,但不安全

let value2: unknown = "hello";
// value2.toUpperCase();  // 错误:需要类型检查

if (typeof value2 === "string") {
  value2.toUpperCase();  // 正确
}

3. interface 和 type 的区别?

  • Interface 支持声明合并,Type 不支持
  • Type 可以定义联合类型、交叉类型等,Interface 主要用于对象
  • Interface 可以通过 extends 扩展,Type 使用 & 交叉类型

4. 如何理解泛型?

泛型是类型参数化,允许在使用时才指定类型,提供类型安全的同时保持代码的灵活性。

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

// T 是类型参数,可以传入任意类型
const result1 = identity<string>("hello");
const result2 = identity<number>(123);

基于 VitePress 构建 | Copyright © 2026-present