← 返回题目列表

satisfies 和 as const 有什么区别?它们如何配合使用?

高频 中等 第 6 / 32 题 更新于 2026/07/29
TypeScriptsatisfiesas const

简化版

as const 用来把值尽量收窄成只读字面量类型;satisfies 用来检查一个值是否满足某个类型,同时尽量保留值自身推断出的精确类型。两者常配合配置对象和常量表使用。

详细版

示例:

const routes = {
  home: '/',
  user: '/user/:id',
} as const satisfies Record<string, string>;

as const 保留 '/''/user/:id' 这样的字面量。 satisfies Record<string, string> 检查所有 value 都是 string。 它和 as Type 不同,satisfies 不会强行把表达式改成目标类型视角。

完整版教学

一、as const 负责收窄字面量

默认情况下,TypeScript 会把很多对象属性推断得更宽。 例如字符串属性会推断成 string,而不是具体的字面量。 as const 会让值尽量保持字面量,并把对象属性变成只读。

const config1 = { mode: 'dark' };
// mode: string

const config2 = { mode: 'dark' } as const;
// readonly mode: 'dark'

这个差异很关键。 如果后续要从常量对象推导联合类型,必须尽量保留字面量信息。

二、satisfies 负责校验形状但保留推断

类型注解会把变量放到目标类型视角下。 satisfies 则是检查表达式满足某类型,同时保留表达式自身更精确的类型。 这非常适合配置对象。

type Theme = Record<string, { color: string }>;

const theme = {
  primary: { color: '#09f' },
  danger: { color: '#f43' },
} satisfies Theme;

如果写成 const theme: Theme = ...key 可能被看成宽泛的 string。 使用 satisfies 后,primarydanger 这些具体 key 更容易保留下来。

三、它和 as 类型断言不是一回事

as Type 是类型断言,偏向告诉编译器“相信我”。 如果断言过宽,可能掩盖错误。 satisfies 是检查,值不满足目标类型时会报错。

type Options = { timeout: number };

const a = { timeout: '3000' } as unknown as Options; // 可能绕过
const b = { timeout: '3000' } satisfies Options; // 报错
写法作用是否保留精确推断风险
: Type标注变量类型可能变宽
as Type类型断言取决于断言
satisfies Type校验满足类型通常保留

这也是 satisfies 高频的原因:它比断言更安全。

四、as const 和 satisfies 配合常量表

前端经常维护路由、权限、事件名、主题 token 等常量表。 我们既希望值保持字面量,又希望整体结构被检查。 这时可以组合使用。

const EVENTS = {
  Login: 'user_login',
  Logout: 'user_logout',
} as const satisfies Record<string, string>;

type EventName = typeof EVENTS[keyof typeof EVENTS];
// 'user_login' | 'user_logout'

流程如下:

对象字面量
  -> as const 收窄 key/value 和 readonly
  -> satisfies 检查结构
  -> typeof 推导联合类型

这套组合非常适合替代部分 enum 场景。

五、satisfies 对额外属性检查很有帮助

配置对象里拼错字段是常见问题。 satisfies 能在对象创建处检查结构。 同时又保留每个字段的具体推断,方便后续精确使用。

type RouteConfig = {
  path: string;
  auth?: boolean;
};

const routes = {
  home: { path: '/', auth: false },
  admin: { path: '/admin', auth: true },
} satisfies Record<string, RouteConfig>;

如果把 path 写成 paht,会直接报错。 这比在使用处才发现 undefined 更早。

六、注意 satisfies 不会改变运行时值

satisfies 是 TypeScript 类型运算。 它不会生成校验代码,也不会在运行时验证接口数据。 如果数据来自用户输入或接口响应,仍然需要运行时校验库。

const config = {
  timeout: 3000,
} satisfies { timeout: number };

记忆钩子:as const 管“推得窄”,satisfies 管“验得准”,两者都不管运行时校验。

数字例子里 3000 可以被保留为字面量,也可以被结构检查为 number。 但运行时传进来的 "3000" 不会因为 satisfies 自动变成数字。

七、常见误区与追问

  • 误区:satisfies 等同于 as 断言。 satisfies 会做满足性检查,断言更像强行告诉编译器。
  • 误区:as const 只是让对象不能修改。 它还会保留字面量类型,是推导联合类型的关键。
  • 误区:satisfies 会生成运行时校验。 它只存在于类型检查阶段,不生成校验逻辑。
  • 追问:为什么不用 : Record<string,string> 类型注解可能让具体 key/value 变宽,satisfies 更容易保留精确推断。
  • 追问:两者组合顺序常怎么写? 常见是对象后接 as const satisfies SomeType
  • 追问:适合什么工程场景? 路由表、权限表、事件名、设计 token、接口字段映射等配置常量。

八、加强记忆

as constsatisfies 不是竞争关系:前者收窄值,后者检查形状。回答时用常量表例子说明:既保留 'user_login' 这种字面量,又检查所有值都是 string,最后再强调它们都不做运行时校验。