我的处境有点奇怪。在过去的两周里,我一直在尝试调试为什么我在 monorepo 内的项目之间丢失类型。我的后端公开了我的客户端使用的类型,但由于某种原因,某些类型只是无法传播并成为any
. 这使得我有一段时间无法在这个项目上开发任何东西。我根据该问题制作了一个示例存储库以进一步展示它。
该项目的构建Yarn Workspaces
和结构如下
apps/site
,导入 tRPC 的 NextJS 客户端AppRouter
apps/backend
,暴露的 Express 后端AppRouter
apps/config
,这是tsconfig
整个项目中使用的基础packages/frontend-shared
,对于这个问题来说并不重要,共享 UI 组件问题可以在客户端内部找到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 …
Run Code Online (Sandbox Code Playgroud) I'm making a project with the TMDB API and trying to make it super type-safe to reinforce some of the TypeScript stuff I'm learning. I'm using Zod to describe the shape of the data returned by the API.
However, I've noticed that depending on the request parameters, the API can send back data with different keys. Specifically, if the API is sending back data from the "trending" endpoint where data.media_type = "movie"
it also has the keys title
, original_title …
我目前正在使用带有 Turborepo 的 monorepo 将所有微服务代码存储在一个存储库中,每个存储库都有 apackage.json
和 a tsconfig.json
,所有这些代码都是用 Nodejs 编写的。
在每个中tsconfig.json
,配置都是相同的
{
"extends": "@tsconfig/node18-strictest-esm",
"compilerOptions": {
"outDir": "build",
"baseUrl": ".",
"paths": {
"@/*": ["./*"],
"@folder-a/*": ["./folder-a/*"], // masked
"@folder-b/*": ["folder-b/*"] // masked
}
},
"exclude": ["node_modules", "build"]
}
Run Code Online (Sandbox Code Playgroud)
我有一项服务A
作为 tRPC 服务器,一项服务B
作为 tRPC 客户端。
AppRouter
当我导入from A
to的类型定义时,如果正确键入,B
类型定义就会变为any
in 。B
A
我研究了一下并发现了类似的问题,看起来路径别名可能会导致这个问题。
有没有任何解决方案/替代原因
我正在尝试 tRCP,并认真遵循此处官方文档中描述的 Next.js 项目的设置: https: //trpc.io/docs/nextjs
然而我注意到有一个依赖 tRPC 的简单组件,比如这样
export const Sample = () => {
const { data } = trpc.useQuery(['hello', { text: 'User' }]);
if (data === undefined) {
return <div>Loading...</div>;
}
return <div>{data.greeting}</div>;
};
Run Code Online (Sandbox Code Playgroud)
由于以下琐碎测试而无法正确测试
describe('Sample', () => {
it('should render successfully', () => {
const { baseElement } = render(<Sample />);
expect(baseElement).toBeTruthy();
});
});
Run Code Online (Sandbox Code Playgroud)
因为没有提供程序的设置,例如withTRCP
用于应用程序本身的 HOC 的设置。因此,测试失败了client
(大概是trcpClient
,与queryClient
)未定义。
我想知道如何正确设置测试,在这种情况下提供正确的客户端,以及模拟查询,因为我在调用测试时没有运行相应的服务器端代码。
所以我想从 Zod 数组中的对象的键中获取类型。该数组也嵌套在一个对象中,只是让事情变得更加困难。
这是我遇到的问题的抽象视图:
const obj = z.object({
nestedArray: z.array(z.object({ valueIWant: z.string() }))
})
// Should be of type z.ZodArray() now, but still is of type z.ZodObject
const arrayOfObjs = obj.pick({ nestedArray: true })
// Grab value in array through z.ZodArray().element
arrayOfObjs.element.pick({ valueIWant: true })
Run Code Online (Sandbox Code Playgroud)
在 Zod 中使用数组会发生什么:
// Type of z.ZodArray
const arr = z.array(z.object({ valueIWant: z.string() }))
const myValue = arr.element.pick({ valueIWant: true })
Run Code Online (Sandbox Code Playgroud)
这是我的实际问题:
我有一个返回以下对象的 API:
export const wordAPI = z.object({
words: z.array(
z.object({
id: z.string(),
word: …
Run Code Online (Sandbox Code Playgroud) TRPC问题
我有一个带有时间线查询的 tweetRouter,它返回推文和 NextCursor,但是当我尝试在组件中访问 useInfiniteQuery 时,会出现错误。
** 类型“{ useQuery: **”上不存在属性“useInfiniteQuery”
翻译:您正在尝试访问useInfiniteQuery
不包含它的对象。
我的组件:
export function Timeline() {
const data = trpc.tweet.timeline.useInfiniteQuery(
{
limit: 10,
},
{
getNextPageParam: (lastPage) => lastPage.nextCursor,
}
);
return (
<Container maxW="xl">
<CreateTweet />
<Box
borderX="1px"
borderTop="1px"
borderColor={useColorModeValue("gray.200", "gray.700")}
>
{data?.tweets.map((tweet) => {
return <Tweet key={tweet.id} tweet={tweet} />;
})}
</Box>
</Container>
);
}
Run Code Online (Sandbox Code Playgroud)
我的 tweet.ts 路由器:
import { z } from "zod";
import { tweetSchema } from "../../../components/CreateTweet";
import { protectedProcedure, publicProcedure, router } …
Run Code Online (Sandbox Code Playgroud) 我正在使用 T3-app(nextjs、tRPC 等),我不知道这些 env 变量错误是否刚刚发生,或者我之前是否没有注意到它们。但是,我在文件中设置了所有环境变量.env
,并在文件中设置了以下配置schema.mjs
:
export const serverSchema = z.object({
DATABASE_URL: z.string().url(),
NODE_ENV: z.enum(["development", "test", "production"]),
NEXTAUTH_SECRET: z.string(),
NEXTAUTH_URL: z.preprocess(
// This makes Vercel deployments not fail if you don't set NEXTAUTH_URL
// Since NextAuth automatically uses the VERCEL_URL if present.
(str) => process.env.VERCEL_URL ?? str,
// VERCEL_URL doesnt include `https` so it cant be validated as a URL
process.env.VERCEL ? z.string() : z.string().url(),
),
GOOGLE_CLIENT_ID: z.string(),
GOOGLE_CLIENT_SECRET: z.string(),
STRIPE_SECRET_KEY: z.string(),
});
export const serverEnv = …
Run Code Online (Sandbox Code Playgroud) 我正在使用 React Typescript,并且按照tRPC 文档进行服务器/客户端设置,但出现此错误。有谁知道为什么部署时会发生这种情况?我在本地使用的时候效果还好吗?
\n8:41:46 AM: TS2339: Property \'createClient\' does not exist on type \'"useContext collides with a built-in method, you should rename this router or procedure on your backend" | "Provider collides with a built-in method, you should rename this router or procedure on your backend" | "createClient collides with a built-in method, you should rename this router or procedure on your backend...\'.\n8:41:46 AM: Property \'createClient\' does not exist on type \'"useContext collides with a built-in …
Run Code Online (Sandbox Code Playgroud) 根据tRPC
文档,查询参数必须遵循此格式
myQuery?input=${encodeURIComponent(JSON.stringify(input))}
Run Code Online (Sandbox Code Playgroud)
我有这个程序:
hello: publicProcedure
.input(z.object({ text: z.string() }))
.output(z.object({ greeting: z.string() }))
.query(({ input }) => {
return {
greeting: `Hello ${input.text}`,
};
}),
Run Code Online (Sandbox Code Playgroud)
手动构造的 URL 返回错误:
const data = {text: "my message"}
const res = await fetch('http://localhost:3000/api/trpc/example.hello?batch=1&input='+encodeURIComponent(JSON.stringify(data)), { method: 'GET' });
const body = await res.json();
console.log(body);
Run Code Online (Sandbox Code Playgroud)
该错误表明查询参数编码不正确?知道出了什么问题吗?使用客户端,它的工作原理:const test = api.example.hello.useQuery({ text: "my message" });
{
"error": {
"json": {
"message": "[\n {\n \"code\": \"invalid_type\",\n \"expected\": \"object\",\n \"received\": \"undefined\",\n \"path\": [],\n \"message\": \"Required\"\n }\n]", …
Run Code Online (Sandbox Code Playgroud) 目前,我的代码如下所示。当突变成功时,我必须重新获取所有数据,因为tasks
不会更新。tasks
提交或删除任务时如何更新客户端?
const { data: sessionData } = useSession()
const {
data: tasks,
refetch: refetchTasks,
} = api.task.getAll.useQuery(undefined, {
enabled: sessionData?.user !== undefined,
})
const createTask = api.task.create.useMutation({
onSuccess: async () => await refetchTasks(),
})
const createTaskValues = (values: { title: string }) =>
createTask.mutate({ title: values.title })
const deleteTask = api.task.delete.useMutation({
onSuccess: async () => await refetchTasks(),
})
Run Code Online (Sandbox Code Playgroud)
聚苯乙烯
useContext()
除非你想每次都重新获取数据,否则使用比调用 refetch 函数更好。
const utils = api.useContext()
const createTask = api.task.create.useMutation({
onSuccess: () => utils.task.getAll.invalidate()
}) …
Run Code Online (Sandbox Code Playgroud)