在 Expo 开发中运用 infer 实现 IDE 路由类型推断的优化实践

61 阅读3分钟

在最近的 Expo 开发过程中,我遇到了一些关于路由参数类型声明的优化问题。

一个有趣的现象,当我在调用 expo 的 useSegments 的时候,发现了 segment 的参数居然自带 IDE 的类型推断,file based 的类型推断,很有意思,于是看了一下源码。

在这里插入图片描述

作为 Python 框架开发者,本身对这种 hint 十分敏感,遂简单调研了解了一下,写下这篇文章。

在处理路由文件结构映射时,我发现 TypeScript 的 infer 关键字在这种场景下表现得尤为出色。通过它,可以从复杂类型中动态推断出路由参数,不仅提升了代码的可读性,还大幅提高了开发效率。

这篇文章主要记录我在开发中的思考过程和具体实现,既是一次总结,也希望能帮助到有类似需求的开发者。


背景:Expo 项目中的路由参数声明

在 Expo 项目中,路由通常与文件目录结构直接相关,比如:

pages/
  ├── index.tsx
  ├── auth/
  │    ├── login.tsx
  │    ├── reset-password.tsx
  └── settings/
       ├── profile.tsx
       ├── security.tsx

每个路由可能需要传递动态参数,比如 /auth/reset-password/:token。传统的方式需要手动声明这些参数的类型,这在路由复杂或变更频繁时,会导致代码冗余且容易出错。

一个有趣的现象,当我在调用 expo 的 useSegments 的时候,发现了 segment 的参数居然自带 IDE 的类型推断,file based 的类型推断,很有意思,于是看了一下源码。看了一下底层,基本上就是通过 infer 来达到这样的效果,如下所示:

在这里插入图片描述

引入 TypeScript 的 infer 优化声明

问题:如何动态从路由文件结构中推断参数类型?

在 TypeScript 中,infer 关键字可以动态推断类型,它在条件类型的配合下,能够从路由路径或文件目录中提取参数名称并生成对应的类型映射。例如,路径 /auth/reset-password/:token 可以自动生成以下类型:

{
  token: string;
}

实现代码

以下是一个通过 infer 优化路由参数声明的示例:

export type StrictRouteParamsOutput<Path> = {
  [Key in ParameterNames<Path> as Key extends `${infer Name}` ? Name : Key]: Key extends `${infer Name}` ? string : never;
};

通过这个类型定义:

  1. ParameterNames<Path> 提取路径中所有的动态参数名称(如 :token)。
  2. infer 关键字动态推断参数名称(token),并将其映射为 string 类型。

这一切无需手动干预,路径结构的变更也会自动反映到类型中。


为什么选择 infer

  1. 动态性
    在开发中,路由结构往往会随着需求的变化而不断调整。使用 infer 能够动态适应这些变化,避免手动更新类型声明。

  2. 简化代码
    减少手动编写冗长的类型定义,让类型声明更具表达力和可维护性。

  3. 提升安全性
    借助 TypeScript 的类型推导能力,能够在开发阶段捕获潜在的路由参数错误,减少运行时错误。

总结

在 Expo 开发中,infer 的引入为路由参数声明的动态推导提供了一种优雅的解决方案。通过它,我不仅优化了代码的结构,还避免了手动管理类型时可能引入的错误。这让我深刻感受到 TypeScript 在大型项目中不可或缺的价值。

如果你也在开发 Expo 项目,并面临类似的路由参数声明问题,建议尝试使用 infer,它会让你的代码更清晰、更高效,对框架开发者来说很友好。