TypeScript type 类型别名

介绍

type 用于给任意类型起别名,简化重复复杂类型书写,复用类型。

作用

仅用于 TypeScript 静态类型检查,编译转换为 JavaScript 后会被全部移除,不会生成任何运行时代码。

应用场景

  1. 接口请求状态:loading /success/fail
  2. 订单状态:待付款、已发货、已完成、已取消
  3. 权限角色:admin /user/guest
  4. 性别、文件类型、支付方式
  5. 后端主键有时候数字、有时候字符串(雪花 ID / 数字自增)

基础语法

type 别名名称 = 类型表达式;

区别于 interface:

  • interface 只能描述对象/类结构,支持自动合并、extends 继承;
  • type 支持所有类型:基础类型、联合、交叉、元组、函数、递归类型、泛型,不能同名合并。

基础用法

1. 基础原始类型别名

给简单基础类型起短名,统一项目规范

// 原始类型
type TString = string;
type TNumber = number;
type TBoolean = boolean;
type TNull = null;
type TUndefined = undefined;

// 使用
const name: TString = "张三";
const age: TNumber = 20;

2. 字面量类型(字符串/数字/布尔字面量)

限定变量只能取固定值,常用于状态、枚举替代

// 字符串字面量联合
type Status = "success" | "fail" | "loading";
let resStatus: Status = "loading";
// resStatus = "xxx" // 报错,只能指定三个值

// 数字字面量
type Level = 1 | 2 | 3;
const lv: Level = 2;

// 布尔字面量
type TrueOnly = true;
const flag: TrueOnly = true;

3. 对象类型(最常用)

支持可选属性、只读属性、任意索引签名

type User = {
  // 必填属性
  id: number;
  name: string;
  // 可选属性 ?
  avatar?: string;
  // 只读属性 readonly,无法修改
  readonly createTime: number;
  // 索引签名:支持任意字符串key,值为string
  [key: string]: string | number | undefined;
};

const user: User = {
  id: 1,
  name: "李四",
  createTime: Date.now(),
  phone: "13800000000"
};

// user.createTime = 123; // 报错:只读无法修改
user.avatar = "xxx.png"; // 可选属性可后期赋值

4. 函数类型别名

统一约束函数入参、返回值类型

// 普通函数
type AddFn = (a: number, b: number) => number;
const add: AddFn = (x, y) => x + y;

// 无返回值 void
type LogFn = (msg: string) => void;
const log: LogFn = (msg) => console.log(msg);

// 带可选参数
type SayFn = (name: string, age?: number) => string;

5. 元组类型 Tuple

固定长度、固定每个位置类型的数组

type Point = [number, number]; // 坐标 x,y
const p: Point = [10, 20];

// 复杂元组 + 可选元素
type Info = [string, number, boolean?];
const info1: Info = ["小明", 18];
const info2: Info = ["小红", 20, true];

6. 数组类型简写

type NumArr = number[];
type StrArr = string[];
// 等价泛型写法
type NumArr2 = Array<number>;

高级运算符:联合 |、交叉 &

1. 联合类型 |:满足任意一种类型

多个类型或关系,变量可以是其中任意一种

// 数字/字符串ID
type Id = number | string;
const id1: Id = 1001;
const id2: Id = "1002";

// 对象联合
type Cat = { meow(): void };
type Dog = { bark(): void };
type Pet = Cat | Dog;

// 注意:联合类型不能直接访问独有属性,需要类型守卫
const pet: Pet = { meow: () => {} };
// pet.meow() 直接报错
if ("meow" in pet) pet.meow(); // 类型缩小后可用

2. 交叉类型 &:同时满足所有类型(合并对象)

多个类型且关系,融合所有属性

type A = { id: number };
type B = { name: string };
type UserInfo = A & B;

const u: UserInfo = { id: 1, name: "老王" };

// 冲突属性:相同key不同类型会变成 never
type Conflict = { a: string } & { a: number };
// type Conflict = { a: never } 无法赋值

联合 vs 交叉对比

  • A | B:二选一
  • A & B:两者全部拥有

泛型 type(通用可复用类型)

给类型添加泛型参数,适配任意数据结构,项目接口返回体必备

基础泛型

// 通用接口返回结构
type ApiResponse<T> = {
  code: number;
  data: T;
  message: string;
};

// 用户类型
type User = { uid: string; username: string };

// 用户响应类型,传入 User 替换 T
type UserResp = ApiResponse<User>;

const resp: UserResp = {
  code: 200,
  data: { uid: "u001", username: "张三" },
  message: "成功"
};

多泛型参数

type Pair<T, K> = { key: T; value: K };
const pair: Pair<string, number> = { key: "count", value: 10 };

泛型约束 extends

限制泛型必须满足指定结构

type HasId = { id: number };
type ItemResp<T extends HasId> = { list: T[] };

type Book = { id: number; title: string };
const bookList: ItemResp<Book> = { list: [{ id: 1, title: "TS教程" }] };

类型提取工具(配合 type 高频使用)

1. typeof:提取变量的类型

从已有变量反向生成类型,不用重复定义

const userObj = { id: 1, name: "小李" };
type UserType = typeof userObj;
// 等价 type UserType = { id: number; name: string }

2. keyof:提取对象所有键的联合类型

type User = { id: number; name: string };
type UserKeys = keyof User; // "id" | "name"

// 工具函数约束对象key
function getValue<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

3. 内置工具类型(全部基于 type 实现)

Partial:所有属性变为可选

type User = { id: number; name: string };
type PartialUser = Partial<User>;
// { id?: number | undefined; name?: string | undefined }

Required:所有属性变为必填

type RequiredUser = Required<PartialUser>;

Readonly:所有属性只读

type ReadOnlyUser = Readonly<User>;

Pick:挑选指定属性生成新类型

type SimpleUser = Pick<User, "id">; // { id: number }

Omit:剔除指定属性生成新类型

type UserWithoutId = Omit<User, "id">; // { name: string }

Exclude:从联合中剔除类型

type AllStatus = "success" | "fail" | "loading";
type SuccessStatus = Exclude<AllStatus, "fail" | "loading">;
// "success"

Extract:提取联合中匹配的类型

type FailStatus = Extract<AllStatus, "fail">;

ReturnType:提取函数返回值类型

const fn = () => ({ id: 1 });
type FnReturn = ReturnType<typeof fn>; // { id: number }

常量断言 as const 配合 type 锁定字面量

普通数组是 string[],as const 转为固定字面量联合

const roles = ["admin", "visitor"] as const;
type Role = (typeof roles)[number]; // "admin" | "visitor"

递归 type(树形、嵌套结构)

type 支持自引用递归,用于菜单、树形数据

type TreeNode = {
  label: string;
  children?: TreeNode[]; // 递归引用自身
};

const tree: TreeNode = {
  label: "根目录",
  children: [
    { label: "子节点1" },
    { label: "子节点2", children: [{ label: "孙子节点" }] }
  ]
};

type 扩展对象(交叉 &)vs interface extends

type 扩展:交叉 &

type Base = { id: number };
type User = Base & { name: string };

interface 扩展:extends

interface Base { id: number }
interface User extends Base { name: string }

核心区别汇总

功能 type 类型别名 interface 接口
原始/联合/元组/函数 ✅ 支持 ❌ 不支持
对象描述 ✅ ✅
同名重复定义 ❌ 直接报错 ✅ 自动合并
继承扩展 使用 & 交叉 使用 extends
配合 class 实现 可以,但不推荐 推荐
递归类型 ✅ 支持 ✅ 支持

使用场景选择

  1. 优先用 type
    • 定义联合、交叉、元组、函数、简单类型别名
    • 一次性复合类型,不需要外部扩展合并
  2. 优先用 interface
    • 定义类、实体对象,需要多处扩展、同名合并
    • 面向面向对象开发(class implements)

常见坑与易错点

1. type 不允许重复同名定义

type T = { a: number };
type T = { b: string }; // 报错:重复标识符

interface 同名会自动合并,type 不行。

2. 联合类型无法直接访问独有属性

需要用 in / 类型判断缩小类型范围才能访问独有字段。

3. 交叉类型属性冲突会变成 never

type T = { x: string } & { x: number };
// T["x"] = never,无法赋值任何值

4. type 不能用于类 implements 限制(不推荐)

class 实现接口优先用 interface,type 虽然能运行但不符合规范。

5. 区分类型别名和值变量

type 仅存在于编译期,打包后会被删除,运行时不存在,不能当做变量使用。


案例

后端接口类型封装

// 1. 基础状态、编码字面量
type ResCode = 200 | 401 | 404 | 500;
type OperateStatus = "ok" | "error";

// 2. 通用泛型返回体
type ApiResult<T> = {
  code: ResCode;
  status: OperateStatus;
  data: T;
  msg: string;
};

// 3. 业务实体
type User = {
  userId: string;
  username: string;
  readonly createAt: number;
  avatar?: string;
};

// 4. 分页包装类型
type PageData<T> = {
  list: T[];
  total: number;
  pageNum: number;
  pageSize: number;
};

// 5. 组合业务类型
type UserPageResp = ApiResult<PageData<User>>;

// 模拟接口返回
function getUserPage(): UserPageResp {
  return {
    code: 200,
    status: "ok",
    msg: "查询成功",
    data: {
      list: [{ userId: "u001", username: "张三", createAt: 1780000000 }],
      total: 1,
      pageNum: 1,
      pageSize: 10
    }
  };
}

原文出处:/show_1GW3eWpclvRg.html