TypeScript satisfies 运算符:校验与推导兼得

satisfies(TS 4.9+)让值在保持精确推导类型的同时满足类型约束。本文讲解它解决的类型拓宽问题与配置对象类型安全的实战模式。

最佳实践
类型结构与组件组合插画

config satisfies Config 检查 config 符合 Config 类型,但保留 config 自身的精确类型(字面量类型不拓宽)。与类型标注(会拓宽)和 as(不检查)相比,satisfies 是"既要校验又要精确"的唯一答案。

类型拓宽的问题

type Theme = 'light' | 'dark';

// 类型标注:安全但丢失精确性
const theme: Theme = 'light';
// theme 的类型是 Theme——不再是字面量 'light'

// as 断言:精确但不安全
const theme2 = 'light' as Theme;
// 写错也不报错:'ligt' as Theme 照样通过

标注丢失精确类型,断言放弃检查——两害之间的空白由 satisfies 填补。

satisfies 解法

const theme = 'light' satisfies Theme;
// ✅ 校验:必须是 Theme 的成员('ligt' 会报错)
// ✅ 精确:类型仍是字面量 'light'

实战:类型安全的配置对象

type Route = { path: string; method: 'GET' | 'POST' | 'PUT' | 'DELETE' };

const routes = {
  listUsers: { path: '/users', method: 'GET' },
  createUser: { path: '/users', method: 'POST' },
} satisfies Record<string, Route>;

// 精确推导的回报:
routes.listUsers.method  // 类型是 'GET'(不是 'GET'|'POST'|...)
routes.createUser.path   // 自动补全精确可用
routes.badRoute          // 编译报错——key 不存在

API 路由表、主题配置、功能开关——所有"配置即代码"场景的标配写法。

与映射类型联动

satisfies 保留的字面量类型让后续类型编程更精确:

type RouteNames = keyof typeof routes;  // 'listUsers' | 'createUser'
type GetRoutes = { [K in keyof typeof routes]: typeof routes[K]['method'] extends 'GET' ? K : never }[keyof typeof routes];

常见问题(FAQ)

Q:satisfies 和 as const 的区别?

as const 冻结值(深只读 + 全字面量化)但不做约束校验;satisfies 校验约束但不改变可变性。两者可组合:config satisfies Config 内部字段按需 as const。

Q:能用于函数返回值吗?

可以——return value satisfies Result 在返回处双重确认。配合显式返回类型注解,错误定位更精准。

Q:旧版本 TS 没有这个怎么写?

升级 TS。临时方案:辅助函数 const check = <T extends Route>(t: T) => t——但原生语法可读性完胜。


参考文档

本文依据公开文档整理,示例需按项目依赖版本验证;不将文档中的性能描述视为本项目实测结果。

延伸阅读

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台