TypeHero:开源TypeScript类型挑战平台架构与开发实战
1. 项目概述:一个面向开发者的现代编程练习平台
如果你是一名前端或全栈开发者,正在学习 TypeScript,或者想通过解决实际问题来提升自己的类型体操和算法能力,那么你很可能已经听说过或者正在寻找一个像 LeetCode 那样的平台,但更专注于 TypeScript 的类型系统。今天要聊的typehero/typehero正是这样一个项目。它不是一个简单的代码库,而是一个完整的、开源的、社区驱动的编程挑战平台,核心目标就是让开发者在一个友好、现代化的环境中,通过解决精心设计的题目来精通 TypeScript。
简单来说,TypeHero 可以理解为 “TypeScript 版的 LeetCode” 或 “专注于类型层面的 Codewars”。但与那些通用算法平台不同,TypeHero 的题目设计完全围绕 TypeScript 的类型系统展开。这意味着你解决的问题不是写运行时逻辑,而是编写纯粹的类型定义,让 TypeScript 的类型检查器来验证你的答案是否正确。这对于深入理解 TypeScript 的高级特性,如条件类型、映射类型、模板字面量类型、递归类型等,有着无与伦比的实践价值。项目采用 Next.js 构建,拥有漂亮的用户界面、完整的用户系统、题目提交与验证流程,以及活跃的社区讨论区,是一个成熟度相当高的开源产品。
2. 核心架构与技术栈拆解
要理解 TypeHero 如何运作,我们需要深入其技术架构。作为一个全栈应用,它巧妙地融合了现代 Web 开发的最新技术,以提供流畅的开发者体验。
2.1 前端:Next.js 与 Tailwind CSS 的完美组合
TypeHero 的前端基于Next.js 14构建,并充分利用了其App Router新范式。App Router 基于 React Server Components,这使得 TypeHero 能够实现出色的初始加载性能和搜索引擎优化。页面布局、题目列表等静态或半静态内容可以在服务器端直接渲染为 HTML,快速送达用户浏览器。而需要交互的部分,如代码编辑器、提交按钮,则作为 Client Components 被按需加载。
提示:选择 Next.js 而非传统的 CRA 或 Vite,对于 TypeHero 这类内容导向且需要良好 SEO 的应用至关重要。题目库、用户解决方案都是希望被搜索引擎收录的宝贵内容,服务端渲染能力是刚需。
样式方面,项目采用了Tailwind CSS。这保证了 UI 的高度可定制性和开发效率。从实际代码看,TypeHero 的界面设计清新、现代,交互反馈细腻,这得益于 Tailwind 实用优先的原子化 CSS 理念,让开发者可以快速构建一致的设计系统,而无需在多个 CSS 文件间跳转。
状态管理上,由于 Next.js App Router 深度集成了 Server Actions 和缓存机制,许多状态(如用户认证状态、题目数据)可以通过服务端直接获取并传递给组件,这减少了对前端全局状态管理库(如 Redux、Zustand)的重度依赖,使数据流更清晰。
2.2 核心交互:基于 Monaco Editor 的在线编码环境
平台的核心体验在于那个功能强大的在线代码编辑器。TypeHero 集成了Monaco Editor,也就是 VS Code 所使用的编辑器内核。这为开发者提供了近乎本地开发的体验:语法高亮(针对 TypeScript 类型语法做了特别优化)、智能提示、自动补全、错误波浪线、快捷键支持等。
但 TypeHero 的 Monaco Editor 配置有其特殊性。通常,Monaco 用于编辑.ts或.tsx文件中的值空间代码。而在 TypeHero 中,编辑器区域主要用于编写类型空间的代码。例如,你可能会看到一个函数签名type MyType = ...,你的任务是在等号右侧填入类型定义。因此,编辑器需要配置特定的 TypeScript 语言服务,使其对类型别名、接口、泛型等提供最精准的提示,同时可能屏蔽掉一些运行时 API 的提示,以减少干扰。
编辑器与后端的交互流程是:用户在编辑器中编写类型解决方案 -> 点击提交 -> 前端将代码发送至评估服务器 -> 服务器在一个隔离的安全环境中运行 TypeScript 编译器,对你的类型定义进行验证 -> 返回验证结果(通过/失败及具体错误信息) -> 前端直观展示结果。
2.3 后端:无服务器函数与类型评估引擎
TypeHero 的后端架构充分体现了现代 Jamstack 应用的思路。它大量使用了Vercel 的无服务器函数来处理动态请求,如用户认证、题目提交、解决方案获取等。这种架构的好处是弹性伸缩、按需付费,并且与作为部署平台的 Vercel 无缝集成。
最复杂的后端逻辑莫过于类型评估引擎。当用户提交一个类型挑战的答案时,后端不能简单地执行这段代码,因为它只是类型定义。评估引擎需要做的是:
- 构造测试套件:每个题目都预定义了一系列 TypeScript 测试用例。这些用例通常以“期望类型
X可赋值给Y”或“期望类型X不可赋值给Y”的形式存在。 - 创建沙盒环境:在一个安全的、隔离的 Node.js 环境中,启动一个 TypeScript 编译器实例。通常会使用
ts-node或直接调用 TypeScript Compiler API。 - 注入用户代码:将用户提交的类型定义与预置的测试用例代码组合成一个完整的 TypeScript 模块。
- 执行类型检查:运行编译器,只进行类型检查(
--noEmit),不生成任何 JavaScript 代码。分析编译器的诊断信息。 - 验证结果:如果诊断信息中没有任何错误(意味着所有测试用例的类型约束都满足),则判定为通过;否则,提取相关的类型错误信息返回给前端,指导用户修正。
这个引擎的稳定性和性能至关重要。它需要能够安全地执行任意用户提交的 TypeScript 类型代码(虽然类型代码通常无害,但复杂的递归类型可能导致编译器陷入循环,需要有超时机制)。
2.4 数据层:Prisma 与 PostgreSQL
TypeHero 使用Prisma作为 ORM 来操作PostgreSQL数据库。Prisma 以其类型安全的数据库查询而闻名,这与 TypeHero 整个项目强调类型安全的理念高度契合。通过 Prisma Schema,项目清晰地定义了数据模型,如User、Challenge、Submission、Solution、Star等。
数据库存储了用户信息、题目描述、测试用例、用户提交记录、点赞的解决方案等所有核心数据。Prisma Client 生成的强类型查询,使得在 Next.js 的 Server Components 或 Server Actions 中访问数据库时,能获得极佳的开发体验和编译时安全性。
2.5 身份认证与社区功能
平台支持多种登录方式,包括 GitHub OAuth 和电子邮件密码登录,这由NextAuth.js处理。NextAuth.js 与 Next.js 集成度很高,简化了复杂的认证流程。
社区功能是 TypeHero 的活力来源。用户可以对自己喜欢的题目解决方案点赞,这形成了每个解决方案的“热度”。热门解决方案会被优先展示,为其他学习者提供了高质量的学习范本。此外,围绕每个题目的讨论区,允许用户提问、分享心得,形成了一个积极的学习闭环。
3. 从零开始:本地开发环境搭建与运行
如果你想为 TypeHero 贡献代码,或者仅仅是想在本地运行一个副本进行探索,以下是详细的步骤。我假设你已具备基本的 Node.js 和 Git 操作知识。
3.1 环境准备与依赖安装
首先,确保你的系统满足以下条件:
- Node.js: 版本 18.17 或更高。推荐使用 LTS 版本。你可以使用
nvm来管理多个 Node 版本。 - Git: 用于克隆代码库。
- 数据库: 你需要一个本地或远程的 PostgreSQL 数据库实例。本地快速启动推荐使用 Docker:
docker run --name typehero-db -e POSTGRES_PASSWORD=yourpassword -p 5432:5432 -d postgres:16。 - 包管理器: 项目使用
pnpm作为包管理器,因其速度快、磁盘效率高。可通过npm install -g pnpm安装。
接下来,克隆仓库并安装依赖:
# 克隆项目 git clone https://github.com/typehero/typehero.git cd typehero # 安装依赖 (使用 pnpm) pnpm install这个过程会下载所有必要的依赖包,包括 Next.js、Prisma、Tailwind CSS 等。
3.2 数据库配置与初始化
TypeHero 依赖 PostgreSQL。在项目根目录下,复制环境变量示例文件并配置你的数据库连接:
# 复制环境变量文件 cp .env.example .env打开新创建的.env文件,找到DATABASE_URL变量,将其修改为你的 PostgreSQL 连接字符串。例如,对于上面 Docker 启动的数据库:
DATABASE_URL="postgresql://postgres:yourpassword@localhost:5432/typehero?schema=public"然后,运行 Prisma 迁移命令来创建数据库表结构:
# 推送 Prisma Schema 到数据库,生成表 pnpm db:push # (可选) 如果项目提供了种子数据,运行以下命令填充初始数据(如内置的挑战题目) pnpm db:seeddb:push命令会根据prisma/schema.prisma文件直接同步数据库结构,适用于开发环境。在生产环境中,更推荐使用prisma migrate dev来生成并应用可版本控制的迁移文件。
3.3 运行开发服务器
完成数据库设置后,你就可以启动开发服务器了:
pnpm dev默认情况下,Next.js 开发服务器会在http://localhost:3000启动。打开浏览器访问该地址,你应该能看到 TypeHero 的本地运行版本。
注意:首次运行时,你可能需要以管理员身份登录。查看项目文档或种子脚本,了解默认的管理员账户信息。通常,种子脚本会创建一个测试用户。
3.4 实操心得:本地开发常见陷阱
- 端口冲突:如果 3000 端口被占用,Next.js 会自动尝试其他端口。你可以通过修改
package.json中的dev脚本,显式指定端口:next dev -p 3001。 - 数据库连接失败:这是最常见的问题。确保:
- PostgreSQL 服务正在运行 (
docker ps查看容器状态)。 .env文件中的DATABASE_URL完全正确,包括用户名、密码、主机、端口和数据库名。- 数据库防火墙(如果使用云数据库)允许你的 IP 连接。
- 可以尝试使用
pg_isready -h localhost -p 5432或图形化工具(如 DBeaver)测试连接。
- PostgreSQL 服务正在运行 (
- PNPM 安装问题:如果
pnpm install失败,可以尝试删除node_modules和pnpm-lock.yaml后重试。确保你的 pnpm 版本较新。 - 类型错误:克隆仓库后,VS Code 可能会报一些类型错误。首先运行
pnpm type-check进行全项目类型检查。很多错误可能是由于依赖未完全安装或数据库未生成 Prisma Client 导致的。运行pnpm prisma generate可以重新生成 Prisma Client 类型。
4. 核心功能模块深度解析
4.1 挑战题目系统:设计与实现
挑战是 TypeHero 的灵魂。每个挑战都是一个独立的模块,位于apps/web/src/app/(play)/challenge/[slug]/page.tsx这样的动态路由下。一个挑战通常包含以下几个部分:
- 描述文档:使用 MDX 或富文本格式,解释题目要求、示例输入输出,并教授相关的 TypeScript 知识点。
- 初始代码骨架:提供一个未完成的 TypeScript 类型定义,例如
type MyPick<T, K> = any,用户的任务是替换掉any。 - 测试套件:这是隐藏的,位于服务器端。它定义了一系列断言,例如:
这里的// 测试用例示例 (概念性) import type { Equal, Expect } from '@type-challenges/utils'; type cases = [ Expect<Equal<MyPick<{ a: number; b: string }, 'a'>, { a: number }>>, Expect<Equal<MyPick<{ a: number; b: string }, 'b'>, { b: string }>>, Expect<Equal<MyPick<{ a: number; b: string }, 'a' | 'b'>, { a: number; b: string }>>, ]Equal和Expect是类型测试工具,来自流行的@type-challenges/utils包。它们利用 TypeScript 的条件类型和泛型,在类型层面判断两个类型是否完全相同。
题目的难度有分级(简单、中等、困难),并且有标签系统(如“数组”、“对象”、“递归”),方便用户筛选。题目数据存储在数据库中,但描述和初始代码可能也以文件形式存在,便于管理和版本控制。
4.2 解决方案提交与验证流程
这是平台最核心的技术流程。让我们跟踪一次完整的提交:
- 用户操作:用户在编辑器中完成代码,点击“提交”按钮。
- 前端处理:前端应用捕获编辑器内容,通过一个
fetchAPI 调用发送到/api/challenge/submit这样的端点。请求体包含挑战ID、用户代码和可能的语言版本。 - API 路由:在 Next.js 的
app/api/challenge/submit/route.ts中,处理 POST 请求。这里会进行基础验证(如用户是否登录、挑战是否存在)。 - 调用评估服务:API 路由将核心的验证逻辑委托给一个独立的“评估服务”。这个服务可能是一个无服务器函数,也可能是一个常驻的微服务。它将用户代码与对应挑战的测试套件拼接。
- 安全沙盒执行:评估服务在一个隔离的容器或
worker_threads中,启动一个干净的 TypeScript 编译环境。这是为了防止恶意代码(虽然类型代码风险低,但防患于未然)和避免资源耗尽(通过设置超时)。 - 类型检查与判断:对拼接后的代码运行
tsc --noEmit --strict。分析输出的诊断信息:- 如果没有错误,且所有
Expect测试都通过(实际上是通过类型检查间接判断),则判定为成功。 - 如果有错误,则提取错误信息。关键的一步是过滤:需要过滤掉那些由测试用例本身(如
Expect<...>)产生的、与用户代码无关的错误,只保留指向用户编写部分的错误信息。
- 如果没有错误,且所有
- 保存与反馈:将提交结果(成功/失败、错误信息、执行时间)保存到数据库的
Submission表中。然后将结果返回给前端API路由,再最终呈现给用户。如果成功,UI 会显示庆祝动画,并可能解锁新的挑战或成就。
4.3 用户系统与进度追踪
TypeHero 鼓励持续学习。用户的个人主页会展示丰富的统计数据:
- 已解决挑战数:按难度分类统计。
- 提交历史:所有尝试的记录,包括成功和失败的。
- 获得的点赞数:来自其他用户对其分享的解决方案的认可。
- 排名或积分:有些平台会引入积分系统,根据解决挑战的难度和速度给予积分,形成排行榜。
这些数据通过 Prisma 查询聚合,在服务器组件中高效获取并展示。进度追踪不仅提供了成就感,也帮助用户了解自己的强项和薄弱环节。
4.4 社区解决方案与点赞系统
解决一个挑战后,用户可以选择将自己的解决方案发布到社区。发布的解决方案会包含代码、简要解释和关联的挑战。其他用户可以浏览这些方案,点赞他们认为优雅或巧妙的方案。
这个功能的实现涉及几个关键点:
- 去重与审核:平台可能需要简单的去重检查,防止完全相同的解决方案刷屏。也可以引入举报机制。
- 热度排序:解决方案列表通常按点赞数、发布时间等综合排序。这需要在数据库查询时使用
ORDER BY和可能的加权算法。 - 实时性:点赞动作可以通过 Next.js 的 Server Actions 或 API Route 配合乐观更新来实现,即前端先假设点赞成功更新UI,然后向后端发送请求,如果失败则回滚,以提供流畅的交互体验。
5. 为 TypeHero 贡献:从 Issue 到 PR 的全流程
TypeHero 是一个开源项目,欢迎社区贡献。无论是修复 bug、添加新功能,还是设计新的挑战,你的参与都很有价值。
5.1 寻找合适的贡献点
- 查看 Issues:前往 GitHub 仓库的 Issues 页面。维护者通常会标记
good first issue或help wanted的标签,这些是专门为新手贡献者准备的入门级任务。 - 理解项目路线图:查看项目的
README.md、CONTRIBUTING.md以及 Discussions 板块,了解项目未来的发展方向,看看是否有你感兴趣且有能力完成的功能。 - 从小处着手:修复一个错别字、改进一段文档、优化一个组件的样式,都是极好的开始。这能帮助你熟悉项目的代码提交流程和协作规范。
5.2 开发工作流详解
- Fork 仓库:在 GitHub 上点击 Fork 按钮,创建属于你自己的项目副本。
- 克隆本地:
git clone https://github.com/你的用户名/typehero.git - 添加上游远程:为了同步原仓库的最新更改,添加 upstream 远程:
git remote add upstream https://github.com/typehero/typehero.git - 创建功能分支:永远不要在
main分支上直接开发。为你的功能或修复创建一个描述性的分支:git checkout -b fix-typo-in-readme或feat/add-new-challenge-hello-world。 - 进行修改:在本地进行代码更改。确保遵循项目的代码风格(通常有 ESLint 和 Prettier 配置,运行
pnpm lint和pnpm format进行检查和格式化)。 - 提交更改:使用清晰的提交信息。推荐使用约定式提交,例如:
fix(web): correct typo in landing page headline或feat(challenges): add ‘Trim Left’ challenge。 - 同步上游:在推送前或解决冲突时,从上游拉取最新更改:
git fetch upstream main然后git rebase upstream/main。变基可以保持提交历史的整洁。 - 推送分支:
git push origin your-branch-name - 创建 Pull Request:在你的 GitHub Fork 仓库页面上,会提示你为新推送的分支创建 PR。点击后,选择将你的分支合并到原仓库的
main分支。在 PR 描述中,详细说明你的更改内容、原因以及如何测试。
5.3 创建新的 TypeScript 挑战
这是最具特色的贡献方式之一。假设你想添加一个名为 “String to Union” 的中等难度挑战。
- 设计题目:明确要求。例如:“实现一个将字符串字面量类型转换为由其字符组成的联合类型的泛型
StringToUnion<T>。” - 创建测试用例:这是核心。你需要在对应的目录(如
packages/challenges/src/medium/string-to-union.test.ts)创建测试文件。测试用例必须全面,覆盖边界情况。import type { Equal, Expect } from '@type-challenges/utils' type cases = [ Expect<Equal<StringToUnion<''>, never>>, Expect<Equal<StringToUnion<'t'>, 't'>>, Expect<Equal<StringToUnion<'hello'>, 'h' | 'e' | 'l' | 'l' | 'o'>>, Expect<Equal<StringToUnion<'coronavirus'>, 'c' | 'o' | 'r' | 'o' | 'n' | 'a' | 'v' | 'i' | 'r' | 'u' | 's'>>, ] - 创建题目模板:在对应的模板文件(如
packages/challenges/src/medium/string-to-union.ts)中,给出初始代码骨架和问题描述。// 问题描述 // 实现 StringToUnion<T>,将字符串转换为字符联合类型 type StringToUnion<T extends string> = any // 你的实现代码写在这里 - 验证挑战:运行项目的测试命令(如
pnpm test challenges),确保你的测试用例能正确通过一个标准的实现(你需要先自己实现一个StringToUnion来验证),并且能正确拒绝错误的实现。 - 提交 PR:将测试文件和模板文件一起提交,并在 PR 中解释挑战的思路和预期考察的知识点(如模板字面量类型、递归、条件类型)。
5.4 贡献注意事项与心得
- 沟通先行:如果你打算进行重大的功能改动,最好先在相关的 Issue 或 Discussion 中提出你的想法,与维护者达成共识后再开始编码,避免做无用功。
- 测试!测试!测试!:任何代码修改,尤其是核心逻辑(如评估引擎、API路由),都必须附带相应的测试。运行现有的测试套件,确保你没有破坏任何功能:
pnpm test。 - 关注代码评审意见:维护者或其他贡献者会在你的 PR 中提出修改意见。请以积极的态度对待,这些意见是为了保证代码质量和项目一致性。仔细阅读、讨论并按要求修改。
- 保持 PR 的专注性:一个 PR 只解决一个问题或实现一个功能。不要将多个不相关的修改混在一起,这会使评审变得异常困难。
6. 部署与生产环境考量
虽然 TypeHero 官方提供了托管服务,但了解如何将其部署到自己的环境也是有意义的,无论是用于内部团队培训还是定制化开发。
6.1 部署到 Vercel(推荐)
由于项目本身就是为 Vercel 构建的,部署到 Vercel 是最简单的路径。
- 将你的 Fork 仓库或原仓库导入 Vercel。
- 在项目设置中,配置环境变量(
DATABASE_URL、NEXTAUTH_SECRET、GITHUB_CLIENT_ID等)。 - Vercel 会自动检测这是 Next.js 项目,并运行
build命令。你需要确保package.json中的build脚本正确。 - 部署后,你需要手动运行数据库迁移。可以在 Vercel 的项目设置中配置“构建命令”为
pnpm db:push && pnpm build,但这并非最佳实践。更好的做法是使用 Vercel 的 Postgres 集成,或通过一个单独的、安全的途径(如脚本或管理面板)来运行迁移。
6.2 数据库与评估服务的生产化
- 数据库:生产环境务必使用托管的、高可用的 PostgreSQL 服务,如 AWS RDS、Google Cloud SQL、Supabase 或 Neon。避免使用单点故障的数据库。
- 评估服务:这是生产环境的难点。简单的无服务器函数可能对冷启动时间和执行时长有限制。对于高并发场景,需要考虑:
- 使用常驻的、可水平扩展的微服务(如部署在 Kubernetes 或 Fly.io 上)来运行评估引擎。
- 引入队列(如 BullMQ、RabbitMQ)来异步处理提交请求,避免 HTTP 请求超时。
- 对评估服务进行严格的资源限制和超时控制,防止恶意或意外的无限递归类型拖垮服务。
6.3 环境变量与安全配置
生产环境必须妥善配置以下关键环境变量:
DATABASE_URL:生产数据库连接字符串。NEXTAUTH_SECRET:一个高强度的随机字符串,用于加密会话 Cookie。可以使用openssl rand -base64 32生成。NEXTAUTH_URL:你的生产环境域名。GITHUB_CLIENT_ID和GITHUB_CLIENT_SECRET:如果你启用了 GitHub 登录,需要在 GitHub OAuth Apps 中注册应用以获取。EMAIL_SERVER等:如果启用邮件登录,需配置 SMTP 服务器。
所有这些敏感信息绝不应该提交到代码仓库,必须通过 Vercel 环境变量、AWS Secrets Manager 等安全方式管理。
7. 常见问题与故障排查实录
在实际运行和开发 TypeHero 过程中,你可能会遇到以下问题。这里记录了我踩过的一些坑和解决方法。
7.1 本地开发服务器启动失败
问题现象:运行pnpm dev后报错,例如 “Module not found” 或 “Prisma Client not generated”。
排查步骤:
- 检查依赖:首先确认
pnpm install已成功完成,没有警告。可以尝试删除node_modules和pnpm-lock.yaml后重新安装。 - 检查 Prisma Client:确保已运行
pnpm prisma generate。这个命令会根据schema.prisma生成客户端代码。有时在pnpm install后不会自动运行。 - 检查环境变量:确认
.env文件存在且DATABASE_URL正确,数据库服务可访问。可以尝试运行pnpm db:push来验证数据库连接。 - 检查端口占用:使用
lsof -i :3000查看 3000 端口是否被其他进程占用。
7.2 题目提交一直显示“正在评估”或超时
问题现象:在本地或自部署环境中,提交挑战后,界面一直转圈,最后报错。
排查步骤:
- 查看浏览器网络日志:打开开发者工具的 Network 标签页,查看提交请求的响应。如果是 500 错误,查看响应体中的错误信息。
- 查看服务器日志:在本地终端或部署平台(如 Vercel 的 Logs)中查看后端日志。错误很可能出现在评估服务的无服务器函数或 API 路由中。
- 评估服务超时:无服务器函数默认有执行时间限制(如 Vercel 的 10秒/60秒)。如果某个挑战的测试用例非常复杂,或者用户提交了会导致编译器陷入深度递归的类型代码,可能触发超时。需要在评估逻辑中加入更严格的超时控制,并提前拒绝明显恶意的代码(如超深的递归类型)。
- 依赖缺失:确保评估服务运行环境中安装了正确的 TypeScript 版本和
@type-challenges/utils等依赖。
7.3 数据库迁移冲突
问题现象:在团队协作中,多人同时修改了schema.prisma文件,导致迁移冲突。
解决方案:
- 优先沟通:在修改 Schema 前,最好在团队内同步。
- 解决冲突:如果已经发生冲突,需要手动合并
schema.prisma文件。然后,生成一个新的迁移:pnpm prisma migrate dev --name resolve-conflict。Prisma 会比较合并后的 Schema 与当前数据库状态,生成一个使数据库达到新状态的迁移文件。 - 重置开发数据库:在极端情况下,可以重置开发数据库(注意:这会丢失所有数据):
pnpm db:reset。然后重新应用迁移。这只适用于开发环境。
7.4 类型挑战测试用例编写错误
问题现象:你贡献了一个新挑战,但 CI 测试失败,或者其他用户反馈测试用例无法正确判断。
排查步骤:
- 运行本地测试:使用
pnpm test challenges确保你的挑战测试文件能通过一个正确的实现。 - 验证边缘情况:手动编写几个正确和错误的实现,看看测试用例是否能准确区分。特别注意
never,any,unknown这些特殊类型。 - 使用 TypeScript Playground:将你的测试用例和实现复制到 TypeScript Playground,直观地查看类型推断结果和错误信息。
- 审查
Expect和Equal:确保你正确使用了测试工具类型。Equal<X, Y>只有在X和Y完全相同时才为true。有时你需要的是Extends(可赋值性)判断,而不是严格的相等。
TypeHero 项目是一个绝佳的学习和贡献对象,它融合了前沿的全栈技术、复杂的编译器交互和活跃的社区运营。无论是想深入学习 TypeScript,还是想研究一个中型开源项目的架构,它都提供了丰富的素材。从用户到贡献者的转变,能让你获得远超单纯使用平台的成长。
