Skip to content

TypeScript 基础类型与接口

一、基础类型

1.1 原始类型

typescript
// 基础类型
let str: string = 'hello';
let num: number = 42;
let bool: boolean = true;
let n: null = null;
let u: undefined = undefined;
let sym: symbol = Symbol('id');
let big: bigint = 100n;

// 特殊类型
let any1: any = 'anything';       // 任意类型,放弃类型检查
let unknown1: unknown = 'safe';   // 安全的 any,使用前需类型收窄
let never1: never;                // 永不返回的类型
let void1: void = undefined;      // 无返回值

1.2 联合类型与交叉类型

typescript
// 联合类型 - 或的关系
type StringOrNumber = string | number;

// 交叉类型 - 与的关系
type Named = { name: string };
type Aged = { age: number };
type Person = Named & Aged; // { name: string; age: number }

1.3 字面量类型

typescript
type Direction = 'up' | 'down' | 'left' | 'right';
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';

// const 断言
const config = {
  url: '/api',
  method: 'GET'
} as const;
// typeof config.method = 'GET' 而非 string

二、Interface vs Type

2.1 语法对比

typescript
// Interface - 声明对象类型
interface IUser {
  name: string;
  age: number;
}

// Type - 类型别名
type TUser = {
  name: string;
  age: number;
};

2.2 核心区别

特性interfacetype
扩展方式extends& 交叉
重复声明自动合并 ✅报错 ❌
联合类型不支持支持 ✅
映射类型不支持支持 ✅
implements支持 ✅支持 ✅
typescript
// Interface 声明合并
interface IConfig {
  debug: boolean;
}
interface IConfig {
  env: string;
}
// IConfig = { debug: boolean; env: string }

// Type 不能重复声明
type TConfig = { debug: boolean };
// type TConfig = { env: string }; // ❌ Error

2.3 最佳实践

  • 优先使用 interface:定义对象、类的形状
  • 使用 type:联合类型、交叉类型、工具类型

三、类型守卫与类型收窄

3.1 typeof 守卫

typescript
function padLeft(value: string | number) {
  if (typeof value === 'string') {
    return value.padStart(4, '0'); // value: string
  }
  return String(value).padStart(4, '0'); // value: number
}

3.2 instanceof 守卫

typescript
class Dog { bark() {} }
class Cat { meow() {} }

function speak(animal: Dog | Cat) {
  if (animal instanceof Dog) {
    animal.bark(); // animal: Dog
  } else {
    animal.meow(); // animal: Cat
  }
}

3.3 in 守卫

typescript
interface Fish { swim: () => void }
interface Bird { fly: () => void }

function move(animal: Fish | Bird) {
  if ('swim' in animal) {
    animal.swim(); // animal: Fish
  } else {
    animal.fly();  // animal: Bird
  }
}

3.4 自定义类型守卫

typescript
interface Admin {
  role: 'admin';
  permissions: string[];
}
interface User {
  role: 'user';
  email: string;
}

// 返回类型是 类型谓词
function isAdmin(user: Admin | User): user is Admin {
  return user.role === 'admin';
}

function getPermissions(user: Admin | User) {
  if (isAdmin(user)) {
    return user.permissions; // user: Admin
  }
  return []; // user: User
}

3.5 可辨识联合 (Discriminated Unions)

typescript
interface Circle {
  kind: 'circle';
  radius: number;
}
interface Square {
  kind: 'square';
  sideLength: number;
}
type Shape = Circle | Square;

function getArea(shape: Shape): number {
  switch (shape.kind) {
    case 'circle':
      return Math.PI * shape.radius ** 2;
    case 'square':
      return shape.sideLength ** 2;
    default:
      // exhaustive check
      const _exhaustive: never = shape;
      return _exhaustive;
  }
}

四、高频面试题

Q1: any vs unknown vs never 的区别?

答案:

  • any: 放弃类型检查,可赋值给任意类型,也可接收任意类型
  • unknown: 类型安全的 any,使用前必须类型收窄
  • never: 永不存在的值的类型,用于 exhaustive check

Q2: interface 和 type 什么时候用哪个?

答案:

  • 定义对象结构、类的形状 → interface(支持声明合并、extends 继承)
  • 联合类型、交叉类型、工具类型 → type
  • 简单别名 → type

Q3: 如何实现 exhaustive check?

答案: 在 switch/if 的 default 分支将值赋给 never 类型变量,若有遗漏分支将编译报错。

前端面试知识库