#TypeScript #full-stack #trpc
Input & Output
之前在 Procedure 时传递参数,需要在中间加一个 input()
方法调用,其实除了 input
还有 output
。
这两个方法被称为验证器(Validator),主要用于验证输入或输出,并且还可以推断其类型。
输入验证器(Input)
一般在输入验证器中,我们可以验证一下传递的参数是否正确,使用方法就是在调用 procedure.input()
方法。
在调用时,我们可以传递一些流行的验证器校验如 Zod、Yup 等,当然也可以不适用这些库。
添加一个名为 greet 的 Procedure,这个 Procedure 接收一个 String
类型的参数 name,且 name 必须首字母大写。server/index.ts
// ...
greet: publicProcedure.input(z.object({
name: z.string().regex(/^[A-Z][a-zA-Z]*$/, '输入的名字必须是字母且首字母大写'),
})).query((opt) => {
const { input } = opt; // input 是经过验证的名字
return `Hello, ${input.name}`;
})
// ...
添加后保存文件,重新启动服务器 ts-node server/index.ts
。
这时在客户端程序中调用这个 Procedure,如果传递的参数不是包含 name
属性的对象,就会看到 IDE 提示的错误:
或者传递的属性名称正确但是类型错误也会有对应的提示:
并且即使通过了编译阶段,但是如果不满足我们的校验条件,可以在 catch 中捕获错误信息:
这样,我们就可以在 query
方法中拿到我们希望的参数了。client/index.ts
trpc.greet.query({ name: 'Alice' }).then((data) => {
console.log('Greet=', data);
}).catch((err) => {
console.error('Error:', err.message);
});
输出验证器(Output)
输出验证器一般来说不需要定义,除非:
- 需要检查返回的数据是否正确
- 需要保证不向客户端返回不必要的数据
假设我们需要校验 greet 返回的数据必须是字符串,并且必须以“Hello”开头:server/index.ts
如果返回的数据类型错误,一样可以在 IDE 中看到
greet: publicProcedure.input(z.object({
name: z.string().regex(/^[A-Z][a-zA-Z]*$/, '输入的名字必须是字母且首字母大写'),
})).output((value): string => {
if (typeof value !== 'string') {
throw new Error('返回值必须是字符串');
}
return value;
}).query((opt) => {
const { input } = opt; // input 是经过验证的名字
console.log('接收到名字:', input.name);
return `${input.name}`
})
如果没有以"Hello"开头的话:
可以看到在客户端可以收到一条错误响应,并且响应状态为 500。
只有当满足 output
方法校验后才能拿到我们预期的结果:
greet: publicProcedure.input(z.object({
name: z.string().regex(/^[A-Z][a-zA-Z]*$/, '输入的名字必须是字母且首字母大写'),
})).output((value): string => {
// 必须是字符串并且以Hello开头
if (typeof value !== 'string') {
throw new Error('返回值必须是字符串');
}
if (!value.startsWith('Hello')) {
throw new Error('返回值必须以Hello开头');
}
return value;
}).query((opt) => {
const { input } = opt; // input 是经过验证的名字
console.log('接收到名字:', input.name);
return `Hello ${input.name}`;
})