/ default / 28浏览

TRPC快速入门(4)

#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}`;
})

客户端运行成功

A阿尔不二