独特的符号:如何使用符号确保类型安全

独特的符号:如何使用符号确保类型安全

如果您使用 React 一段时间,您可能已经接触过 React Query 的 queryOptions() 函数。其实现看似非常简单:

export function queryOptions(options: unknown) {  return options;}

登录后复制

然而,其真正的强大之处在于其函数重载签名。那么,它究竟有何特别之处呢?

还不了解函数重载?请参考这篇文章:函数重载:巧妙处理多个函数签名

类型安全的数据库查询

受到 React Query 方法的启发,我创建了一个辅助函数,它可能对非 React 开发者也同样有用:一种创建类型安全数据库查询(例如 SQL 查询)的简便方法。

export declare const queryParamsSymbol: unique symbol;export declare const queryReturnSymbol: unique symbol;export type Query<  TParams extends Record = {},  TReturn extends Record | undefined = undefined,  TStatement extends string = string> = {  statement: TStatement;  [queryParamsSymbol]: TParams;  [queryReturnSymbol]: TReturn;};export function Query<  TParams extends Record = {},  TReturn extends Record | undefined = undefined,  TStatement extends string = string>(statement: TStatement): Query {  return { statement } as Query;}

登录后复制

类似于 queryOptions(),这个函数本身也相当简洁:它接收一个 SQL 语句,将其包装在一个 Query 类型的对象中,然后返回该对象。

这是一个简单的调用示例:

const getUserById = Query('SELECT name, email FROM users WHERE id = $id');

登录后复制

请注意我们如何将两种类型作为泛型参数传递。第一个是必需的查询参数——在本例中为 id。第二个代表查询的返回类型——name 和 email。

在底层,Query() 函数将这两种类型嵌入到返回的对象中,并分别存储在 queryParamsSymbol 和 queryReturnSymbol 中。这些符号被声明为唯一符号,这意味着它们只存在于类型空间中,不会出现在编译后的 JavaScript 代码中。

我使用这些符号来临时存储参数和返回类型,并在需要时检索它们。

type InferQueryParams = TQuery extends Query  ? Params  : never;type UserQueryParams = InferQueryParams;//        ^? { id: number }type InferQueryReturn = TQuery extends Query  ? Return  : never;type UserQueryReturn = InferQueryReturn;//        ^? { name: string; email: string }

登录后复制

InferQueryParams 和 InferQueryReturn 只是辅助类型,用于验证参数和返回类型是否被正确推断。实际上您可能并不需要它们,但它们有助于验证我们的方法。

数据库客户端

现在我们知道如何在查询对象中嵌入参数和返回类型,那么我们如何实际执行这些查询呢?让我们来看一个可以执行类型安全查询的简单数据库客户端:

class DatabaseClient {  async execute<    TParams extends Record,    TReturn extends Record  >(    query: Query,    params: TParams  ): Promise<Array> {    // 执行查询并返回结果    // ...    return [];  }}const db = new DatabaseClient();// 返回类型和参数从查询对象中推断const result = await db.execute(getUserById, { id: 1 });//                                              ^? { id: number }//      ^? Arrayconsole.log(result);

登录后复制

在这个例子中,我们将类型安全的 getUserById 查询对象传递给 db.execute() 方法。由于 Query 类型同时包含参数和返回类型信息,TypeScript 会自动推断它们。我们可以通过将鼠标悬停在 result 上轻松验证这一点,TypeScript 还会提示 id 作为参数对象的属性。

TypeScript 游乐场

您可以在这个 TypeScript 游乐场中找到完整的代码示例:[假设游乐场链接]

以上就是独特的符号:如何使用符号确保类型安全的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2642632.html

(0)
上一篇 2025年3月7日 06:51:55
下一篇 2025年3月7日 06:52:01

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 自动创建 Google Meet

    利用 Google Calendar API 和服务帐号自动化创建 Google Meet 会议 本文将指导您如何使用 Google Calendar API 创建 Google 日历活动,并自动生成 Google Meet 会议链接。我们…

    2025年3月7日
    000
  • 在 Svelte 中与符文类共享符文

    我通常避免在 TypeScript 代码中使用类,倾向于使用函数以简化代码,并利用 tree shaking 的优势避免引入不必要的类方法。 然而,Rich Harris 建议在某些情况下使用符文类可以提高性能,因为它们无需使用 get 和…

    2025年3月7日
    200
  • 从挑战到创造:使用 AWS 和 React 构建博客文章生成器

    免责声明: 本文基于一个项目生成。我仔细检查了所有生成内容,确保其逻辑清晰,与人工撰写方式无显著差异。出于项目目的,我未对 AI 生成内容进行编辑。如有补充说明,会在相应部分标注。 作为一名不断挑战自我的软件工程师,我最近完成了一个融合多项…

    2025年3月7日
    200
  • 开发人员如何使电动汽车充电器能够与移动应用程序通信

    在电动汽车 (ev) 世界中,电动汽车驾驶员最神奇的体验之一就是在移动应用程序上点击“开始”并看到充电器开始工作。 但是这个魔法是如何发生的呢? 让我们深入了解电动汽车充电器和移动应用程序如何通信的幕后旅程。 游戏中的玩家 移动应用程序:这…

    2025年3月7日 编程技术
    200
  • 优化动态网站的移动性能和媒体加载

    提升动态网站的移动端性能和用户体验,尤其是在处理大量媒体内容(图片、视频、交互元素)方面,是一个持续的挑战。虽然在桌面浏览器上表现良好,但移动设备和低速网络环境下的加载速度仍有显著提升空间。高分辨率图像和视频的加载时间过长,以及页面中大量交…

    2025年3月7日
    200
  • 了解软件测试中的语句覆盖率

    软件测试中的语句覆盖率:确保代码完整性 语句覆盖率是衡量软件测试完整性的基础指标,它表示已执行代码语句占总可执行语句的比例。 理解并有效利用语句覆盖率对于开发人员和测试人员至关重要,它能帮助识别未测试代码,降低缺陷风险,最终提升软件质量。 …

    2025年3月7日
    200
  • Diff JSON:简化 JSON 比较

    在 Web 开发中,JSON (JavaScript 对象表示法) 随处可见,但比对 JSON 对象却常常让人头疼,特别是面对嵌套复杂或数据量庞大的情况。本文将深入探讨 JSON 差异比对的意义、重要性,并讲解如何借助工具、库和最佳实践高效…

    2025年3月7日
    200
  • 值得关注的 CMS 趋势

    内容管理系统 (cms) 诞生至今已有二十余年,其发展始终紧跟互联网的步伐,不断满足人们对便捷建站和高效更新内容日益增长的需求。20世纪90年代中期,interwelt和filenet等专有系统曾引领风潮,但进入21世纪初,wordpres…

    2025年3月7日
    200
  • React 项目和状态管理

    每个应用的核心功能在于管理、存储和操作其内部创建或从外部来源获取的数据。 这些数据可以是变量、对象、布尔值等多种形式,涵盖目标编程语言支持的任何数据类型。应用必须能够以任何所需方式存储、修改和使用这些数据。 React是一个基于组件结构的知…

    2025年3月7日
    200
  • Java 脚本中的运算符 ?=

    JavaScript 的安全赋值运算符 ?= 简化了代码中的错误处理,提升了代码的可读性和可维护性,尤其在处理 try-catch 块时非常有效。 ?= 运算符的功能 ?= 运算符检查操作或函数的执行结果。成功则返回结果;失败则返回错误信息…

    2025年3月7日
    200

发表回复

登录后才能评论