You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建强类型且禁止引用不存在属性的TypeScript对象?

嘿,这个需求在TypeScript里实现起来非常顺畅,刚好匹配强类型语言的优势!我给你分享两种实用方案,看哪种更贴合你的场景:

实现强类型查询对象的两种方案

方案1:利用as const和类型推导(最简快捷)

如果你不想手动写接口,直接用const断言就能让TypeScript自动推导出精确的键类型,完美实现编译时的属性检查:

// queries.ts
export const queries = {
  getUser: 'SELECT * FROM users WHERE id = ?',
  getPosts: 'SELECT * FROM posts WHERE user_id = ?'
} as const;

// 在其他文件导入使用
import { queries } from './queries';

// ✅ 完全合法,编译器能精准识别getUser是有效键
const userQuery = queries.getUser;

// ❌ 编译直接报错!提示“类型‘typeof queries’上不存在属性‘getComments’”
const invalidQuery = queries.getComments;

为什么这能生效? as const会让TypeScript把对象的每个属性都锁定为字面量类型,同时把整个对象标记为只读。这样编译器就能严格校验你引用的键是否存在,完全符合你要的“禁止引用不存在属性”的要求。

方案2:手动定义接口+satisfies约束(适合复用类型场景)

如果需要把查询的类型单独抽出来(比如在函数参数、返回值里复用),可以先定义接口,再用satisfies关键字约束对象结构:

// 先明确所有合法的查询键和对应类型
interface QueryMap {
  getUser: string;
  getPosts: string;
}

// 用`satisfies`保证对象符合接口,同时保留自身的字面量类型细节
export const queries = {
  getUser: 'SELECT * FROM users WHERE id = ?',
  getPosts: 'SELECT * FROM posts WHERE user_id = ?'
} satisfies QueryMap;

小提示:如果用const queries: QueryMap = { ... }的方式,变量类型会被拓宽为接口类型,丢失字面量信息;而satisfies既能保证结构合规,又能保留更精确的类型,是TypeScript 4.9+版本的推荐写法。

额外加固:禁止运行时修改对象

如果还想防止在运行时给queries添加或修改属性,可以结合Object.freeze:

export const queries = Object.freeze({
  getUser: 'SELECT * FROM users WHERE id = ?',
  getPosts: 'SELECT * FROM posts WHERE user_id = ?'
} as const);

// ❌ 编译时报错,严格模式下运行时也会报错
queries.getComments = 'SELECT * FROM comments WHERE user_id = ?';

这样从编译到运行阶段,都能彻底保证对象结构的稳定性。

内容的提问来源于stack exchange,提问作者Nathan Friend

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:29:08