ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Redwood 项目中的 TypeScript:从初始化到类型安全的渐进式落地指南

Redwood 项目中的 TypeScript:从初始化到类型安全的渐进式落地指南 Redwood 项目中的 TypeScript从初始化到类型安全的渐进式落地指南【免费下载链接】redwoodRedwoodGraphQL项目地址: https://gitcode.com/gh_mirrors/re/redwoodRedwood 框架仓库根目录为全栈 TypeScript 提供了开箱即用的支持既能以--typescript一键创建 TS 项目也允许既有 JavaScript 项目渐进式迁移。本篇指南以 Redwood 5.x 版本文档为骨架结合仓库源码与真实模板完整覆盖 TS 项目创建、JS 项目转换、自动类型生成、类型检查、路径别名等核心实践帮助你理解 Redwood 类型系统背后的生成机制并在自己项目中稳妥落地。一、快速开始创建 TypeScript 项目Redwood 在项目创建阶段就完整支持 TypeScript创建时只需追加一个选项yarn create redwood-app my-redwood-app --typescript执行后脚手架会生成带有tsconfig.json的 web 与 api 两侧工程以及全 TypeScript 的目录骨架对应仓库中的 packages/create-redwood-app/templates/ts 模板。与 JS 模板相比TS 模板在web/tsconfig.json、api/tsconfig.json与scripts/tsconfig.json中预置了针对 Redwood 结构的paths、rootDirs映射这正是后续自动类型能正常工作的关键下文会详细展开。二、将 JavaScript 项目转换为 TypeScript如果你的项目当初是用 JavaScript 起步的Redwood 提供了渐进式迁移路径不需要一次性重写所有文件。1. 初始化 tsconfig在项目根目录运行yarn rw setup tsconfig该命令会在web与api两侧分别写入tsconfig.json让 VSCode 等编辑器识别这是一个 TypeScript 工程。从源码看packages/cli/src/commands/setup/tsconfig/tsconfig.js该命令支持--force/-f选项用于覆盖已存在的 tsconfig.json 文件其实际逻辑tsconfigHandler.js会根据当前安装的 Redwood 版本从 create-redwood-app 的 TS 模板中拉取web/tsconfig.json与api/tsconfig.json写入磁盘。完成初始化后两侧的jsconfig.json文件就可以删掉了它们只是 JavaScript 时代的等价物。2. 渐进式重命名文件无需一次性迁移全部代码官方推荐的做法是增量进行将普通模块从.js重命名为.ts将包含 React 组件的文件重命名为.tsx。Redwood 在底层使用 Babel 转译 TypeScript见下文运行类型检查一节因此.js与.ts文件可以在同一项目内长期共存、按你的节奏逐步切换。三、核心概念自动类型生成Redwood 类型体系的第一支柱是CLI 自动生成类型开发时yarn rw dev会监听文件变化并持续触发类型生成让你只管写代码类型交给框架若当前没有启动 dev server也可以随时手动刷新yarn rw g types这条命令的别名形式是yarn redwood generate types。生成结果会落在.redwood/types虚拟目录含 Cell 镜像类型等web/types/graphql.d.tsweb 侧基于查询/变更生成的类型api/types/graphql.d.tsapi 侧基于 SDL 生成的 resolver 类型从类型生成文档docs/docs/typescript/generated-types.md可归纳出 Redwood 会生成五类类型web 侧组件、页面、布局等以及 api 侧 services、lib 等的mirror 类型基于 TypeScript 的 virtual directories rootDirs 机制web 侧基于 GraphQL 查询与变更生成的类型web/types/graphql.d.tsapi 侧基于 SDL 生成的 resolver 类型api/types/graphql.d.ts测试、currentUser等辅助类型某些函数如routes.pageName()、useAuth()的类型。生成类型的常见问题如果yarn rw g types报错优先检查 Cells 与 SDLs 中的 GraphQL 操作是否语法合法以及 web 侧的每个 query/mutation 是否都在 api 侧的*.sdl.*文件中定义。若遇到context.currentUser类型显示为 unknown先运行yarn rw g types再重启编辑器的 TypeScript serverVSCode 中通过命令面板执行 TypeScript: Restart TS serverMac 为CmdShiftPWindows 为CtrlShiftP。四、利用生成器学习工具类型当你生成一个 Cell 时例如yarn rw g cell Post如果项目是 TypeScript生成的文件会包含大量工具类型从redwoodjs/web导入以及项目专属类型从types/graphql导入。初次接触不必全部记忆需要时查阅 Utility Types 文档 即可。Redwood 的哲学是先生成、再按需细化例如DbAuthHandler之类的场景可通过泛型获得更精确的类型详见 utility-types.md。五、Redwood 不会强迫你为所有东西标注类型Redwood 的默认类型策略是尽量保持简单自动生成尽可能多的类型不强制你手写每一个细小的类型标注默认不开启strict严格模式。这不是偷懒而是刻意的产品决策降低上手门槛、让生成器产物直接可用。当你对 TypeScript 更熟悉、想要更强的类型安全时可以在web/tsconfig.json与api/tsconfig.json中若用到 scripts还要在scripts/tsconfig.json中将strict设为true来开启严格模式相关注意事项可参考 Strict Mode 文档。六、在两侧之间共享类型web 与 api 是两个独立的 TypeScript 工程共享自定义类型的做法是在项目根目录创建名为types的目录可能需要在项目根手动创建把共享类型放进去重启编辑器的 TypeScript server在 VSCode 中通过命令面板执行 TypeScript: Restart TS server确保当前光标位于.js或.ts文件中。之所以这样可行是因为两侧的tsconfig.json都通过types/*: [./types/*, ../types/*]将根级types目录纳入了模块解析范围——从仓库模板可以清楚地看到这一点web/tsconfig.json、api/tsconfig.json。查询与变更的类型web 侧生成的 GraphQL 类型按操作名命名。例如 Cell 中定义export const QUERY gql # 务必为 GraphQL 操作命名 query FindBlogPostQuery($id: Int!) { blogPost: post(id: $id) { title body } } 之后即可按操作名导入类型import type { FindBlogPostQuery, FindBlogPostQueryVariables, } from types/graphql其中FindBlogPostQuery对应查询返回的数据类型{ title: string, body: string }FindBlogPostQueryVariables对应变量类型{ id: number }。types/graphql这个导入说明符是一个路径映射TypeScript 会先在web/types/graphql.d.ts中查找找不到再去根级types/graphql.d.ts中查找——Redwood 只自动生成前者后者正是上一节共享类型的用武之地。如果你使用生成器创建 Cell这些模板代码会自动写好。Resolver 的类型生成的 Service 也会附带 resolver 类型import type { QueryResolvers, MutationResolvers } from types/graphql import { db } from src/lib/db export const posts: QueryResolvers[posts] () { return db.post.findMany() } export const post: QueryResolvers[post] ({ id }) { return db.post.findUnique({ where: { id }, }) }这些类型会约束 resolver 返回对象必须符合 SDL 中定义的结构如果 Prisma 模型名与 SDL 类型名一致类型生成器会把二者映射起来使 resolver 期望你返回对应的 Prisma 类型——你通常只需直接返回 Prisma 查询结果不必关心如 Prisma 的 DateTime 与 GraphQL 的 String 之间的映射细节。若 SDL 类型与 Prisma 模型名不一致则只依据 SDL 定义生成类型此时若想返回额外字段可在 SDL 中改用自定义类型。对于 union 类型生成器同样会自动处理但如果要返回其他 Prisma 模型可能需要手写 resolver 类型。类型生成的底层实现Redwood 使用 GraphQL Code Generatorgraphql-codegen 为 GraphQL 操作与 SDL 生成类型并配置为使用生成的 Prisma Client 类型保证 resolver 强类型化。默认配置开箱即用但你可以通过项目根目录的./codegen.yml自定义例如将生成类型名转换为大写config: namingConvention: typeNames: change-case-all#upperCasegraphql-codegen 支持codegen.yml、codegen.json、codegen.js等多种配置形式甚至根package.json中的codegen键也可以其底层使用 cosmiconfig 查找配置。需要说明的是目前 Redwood 仅支持其根级config选项。此外还有一个实验性的 sdl-codegen 代码生成器可通过在redwood.toml中开启[experimental] useSDLCodeGenForGraphQLTypes true开启后yarn rw g types会按文件生成 resolver 类型并可配合 eslint 的redwoodjs/service-type-annotations规则在package.json的eslintConfig.overrides中为api/src/services/**/*.ts自动标注类型。七、运行类型检查Redwood 底层用 Babel 转译 TypeScript这意味着严格来说dev 与 build 并不关心 tsc 的检查结果——这也是你能渐进式混用.js与.ts的原因。因此需要显式运行类型检查yarn rw type-check从源码看packages/cli/src/commands/type-check.js该命令的别名是tsc/tc支持指定[sides..]参数默认对 web 与 api 两侧执行并有以下选项选项默认值说明--prismatrue是否先生成 Prisma Client--generatetrue是否先重新生成项目内的类型--verbose/-vfalse打印更多输出其执行流程type-checkHandler.js为先按需生成 Prisma Client再执行yarn rw-gen生成类型最后在 web 与 api 两侧并行运行tsc --noEmit --skipLibCheck任一侧失败都会以非零退出码结束方便接入 CI。正因为先生成、再检查类型检查总能拿到最新生成的类型不会出现缺类型误报。八、使用路径别名Alias Paths路径别名允许你为 import 语句定义自定义快捷方式避免冗长的相对路径。Redwood 默认就把src目录做了别名你还可以在tsconfig.json中进一步扩展。例如将这样的超长导入import { CustomModal } from src/components/modules/admin/common/ui/CustomModal缩短为import { CustomModal } from adminUI/CustomModal只需在tsconfig.json的compilerOptions.paths中追加别名{ compilerOptions: { paths: { src/*: [./src/*, ../.redwood/types/mirror/api/src/*], adminUI/*: [ ./src/components/modules/admin/common/ui/*, ../.redwood/types/mirror/web/src/components/modules/admin/common/ui/* ], types/*: [./types/*, ../types/*], redwoodjs/testing: [../node_modules/redwoodjs/testing/api] } } }注意每个别名都映射了两个路径真实源码路径与.redwood/types/mirror/...镜像路径。../.redwood/types/mirror/web/src/...指向 Redwood 构建时生成的虚拟目录.redwood——它包含了 Cell 等模块的镜像类型因此导入时无需显式写index文件。将源码路径与镜像路径组合在同一别名下即可得到更短更干净的导入// 冗长的写法 import { CustomModal } from src/components/modules/admin/common/ui/CustomModal/CustomModal // 优雅的写法 import { CustomModal } from adminUI/CustomModal仓库中的 TS 模板可以印证这套设计的实际形态web/tsconfig.jsonweb 侧rootDirs同时包含./src、.redwood/types/mirror/web/src、../api/src与.redwood/types/mirror/api/srcsrc/*与types/*均做了多路径映射api 侧api/tsconfig.json则映射src/*、types/*与redwoodjs/testing。脚本侧scripts/tsconfig.json还额外提供了$api/src/*、api/src/*、$web/src/*、web/src/*等跨侧别名。使用路径别名的核心收益有三点提升代码可读性抽象掉复杂的目录层级用有意义的名称引用模块增强可维护性代码与文件结构解耦移动文件时无需改动大量相对导入减少样板代码告别../../src/components/modules/admin/common/ui/式的长前缀。九、总结Redwood 的 TypeScript 支持可以概括为三个关键词自动生成、渐进迁移、按需严格。无论你是从yarn create redwood-app --typescript起步还是通过yarn rw setup tsconfig把既有 JS 项目逐步转 TS都可以借助yarn rw g types与yarn rw type-check这两条命令获得可靠的类型保障而路径别名与跨侧types目录则让代码库在长期演进中保持整洁。想要进一步深入可继续阅读仓库内的 Generated Types、Utility Types 与 Strict Mode 三篇配套文档。【免费下载链接】redwoodRedwoodGraphQL项目地址: https://gitcode.com/gh_mirrors/re/redwood创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表