编程前端开发工程师

常量对象的类型化是如何工作的,带有 as const 特性?在不正确地对这些对象进行类型化时,有哪些优点和问题?

用 Hintsage AI 助手通过面试

答案

在 TypeScript 中,as const 将对象/数组的值和属性转换为只读和字面量类型。这提供了严格的类型化:值不会被 "扩展" 为基本类型,而是保持其具体值。

示例:

const a = { status: 'success' }; // 类型: { status: string } const b = { status: 'success' } as const; // 类型: { readonly status: "success" }

优点:

  • 严格类型化(例如,对字符串进行 switch/case,常量列表)
  • 非常适合用于枚举、Redux 中的 actionTypes、角色列表等。
  • 防止意外更改值

缺点/特性:

  • 属性被设置为只读,尝试更改会导致错误。
  • 粗心使用可能导致类型不兼容(例如,如果需要字符串,但你传递了字面量)。

有陷阱的问题

问题: 如果对字符串数组使用 as const,它将是什么类型,是否可以将其作为普通的 string[] 传递?

答案: 类型将是 readonly ["a", "b", "c"],即只读约束的字面量类型的元组。这样的数组与类型 string[] 不兼容;不能直接传递到期望可变字符串数组的地方。

const arr = ['a', 'b', 'c'] as const; // readonly ["a", "b", "c"] function acceptsStrings(x: string[]) {} acceptsStrings(arr); // 错误!类型不兼容

由于对该主题细微之处缺乏了解而导致的实际错误示例


故事

项目: 将 actionTypes 列表作为常量数组使用 as const,然后尝试将其传递到期望 string[] 的函数中。出现了类型错误,不得不通过 .slice() 或者 [...arr] 显式转换。


故事

项目: 在 Redux 微框架中,将 action.type 的类型定义为通过 as const 的字面量。在实现 switch-case 时忘记了严格类型化,没有处理所有可能的字面量,导致没有进行 exhaustive check - 错误未显现,直到添加了新的 action。


故事

项目: 在自动生成 API 端点时,通过 as const 数组描述其键。尝试将这些键用作普通 Record<string, ...> 的索引失败,因类型不一致—不得不添加转换,或者显式使用数组中的键类型。