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 核心区别
| 特性 | interface | type |
|---|---|---|
| 扩展方式 | 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 }; // ❌ Error2.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 类型变量,若有遗漏分支将编译报错。