我的情况有点奇怪。在过去的两周里,我一直在调试为什么我在monorepo中的项目之间丢失类型。我的后端公开了我的客户端使用的类型,但由于某些原因,某些类型无法通过并成为any
。这使我暂时无法在此项目上开发任何内容。I made a sample repo out of the issue to further showcase it.
该项目使用Yarn Workspaces
构建,其结构如下
apps/site
,导入tRPCAppRouter
的NextJS客户端apps/backend
,公开AppRouter
的快速后端apps/config
,以下是整个项目中使用的基本tsconfig
packages/frontend-shared
,对此问题不重要,共享UI组件
可在客户端in the apps/site/src/lib/ApiProvider.ts
内部发现问题
// The type is imported directly from backend, here we use type alias to make it cleaner
import type { AppRouter, EmailType, ProfileType, Test } from "@company/backend/trpc";
export type { AppRouter } from "@company/backend/trpc";
import { inferProcedureOutput } from "@trpc/server";
// The type is inferred to any
// Also if you hover over the app router, the context is also any
type loginOutputType = inferProcedureOutput<AppRouter["user"]["login"]>;
//Profile type doesn't have test field but it lets me set it
const a: ProfileType = {};
a.test = false;
//Same as well here, but it errors out as it should
const b: EmailType = {};
b.test = false;
//
const t: Test = {}
由于某种原因,tRPC
方法输出的类型被推断为any
,const a
类型是Profile
的别名,但即使我添加了不存在的字段,类型检查器也没有抱怨。const b
和const t
的类型正确
就typescript配置I use this base tsconfig
而言,我的设置是相当标准的,它设置了一些合理的默认值,如strict
以及从它继承的所有其他配置
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Default",
"compilerOptions": {
"composite": false,
"declaration": true,
"declarationMap": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"inlineSources": false,
"isolatedModules": true,
"moduleResolution": "node",
"preserveWatchOutput": true,
"skipLibCheck": true,
"noUncheckedIndexedAccess": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": false
},
"exclude": ["node_modules"]
}
我尝试过修改tsconfig,完全重做,尝试过删除路径别名,清理Yarn缓存,尝试过从前端到后端使用项目引用,但我一直遇到同样的问题
这是非常困难的调试为什么只有 typescript 魔术发生在这里,没有错误或任何种类的东西,我可以看看,我按照tRPC
安装指南,但由于某种原因,一些设置或导致类型被打破。
我有90%的把握这个问题实际上不是tsconfig
的,因为我也从其他人那里复制了整个设置,它仍然导致了相同的类型推断。我不知道还有什么会影响typescript这样做,我最后的手段似乎是将API层制作成一个包,并使用直接导入到我的包中,但这是hacky,将需要相当多的重构,虽然我100%确定我当前的设置确实应该工作
1条答案
按热度按时间vyswwuz21#
只是相信@oae的回答/评论,它为我解决了这个问题
问题是我在后端也使用了路径别名,一旦我在后端使用了相对路径,前端就能正确地得到类型
编辑:但我认为有一个更优雅的解决方案,那就是在将别名导入转换为相对导入后直接发出js输出文件,这可以通过https://github.com/justkey007/tsc-alias实现,例如: