You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用io-ts实现API请求对象的严格属性校验?

使用io-ts实现API输入的严格校验(禁止未声明属性)

问题背景

我正在使用io-ts进行API输入校验,需要确保请求对象中不存在未声明的属性。

定义的请求接口如下:

const Request = t.type({
  id: t.string,
  name: t.string
});

测试输入内容:

const req = { 
  id: 'r1',
  name: 'req 1',
  description: 'desc' // 该属性未在Request类型中声明
}

执行校验代码:

const r = Request.decode(req);

if (isLeft(r)) {
    console.log(PathReporter.report(r));
} else {
    console.log("validate success");
}

实际校验显示成功,但期望因存在未声明的description属性而触发错误,请问如何基于io-ts实现这种严格校验?

解决方案

方法1:直接使用t.strict替代t.type

io-ts中的t.type会忽略对象中多余的属性,而t.strict会开启严格模式,不允许存在任何未声明的属性。只需修改类型定义:

const Request = t.strict({
  id: t.string,
  name: t.string
});

此时重新执行校验,多余的description属性会触发校验失败,PathReporter会输出对应的错误信息。

方法2:通过t.refinement添加额外校验逻辑

如果需要保留t.type的原有特性,可使用t.refinement给类型添加严格属性检查:

import * as t from 'io-ts';

// 先定义基础类型
const RequestBase = t.type({
  id: t.string,
  name: t.string
});

// 封装严格校验的类型
const Request = t.refinement(RequestBase, (obj) => {
  const allowedKeys = new Set(Object.keys(RequestBase.props));
  // 检查输入对象的所有属性都在允许列表中
  return Object.keys(obj).every(key => allowedKeys.has(key));
}, 'StrictRequest');

// 执行校验
const r = Request.decode(req);
if (isLeft(r)) {
  console.log(PathReporter.report(r));
} else {
  console.log("validate success");
}

当存在未声明属性时,refinement会返回false,校验失败并输出错误提示。

方法3:自定义严格解码函数

通过fp-ts的管道操作,先完成基础校验,再对比输入对象与校验后对象的属性数量,判断是否存在多余属性:

import * as t from 'io-ts';
import { pipe } from 'fp-ts/function';
import { map } from 'fp-ts/Either';

// 自定义严格解码函数
const strictDecode = <T>(type: t.Type<T>) => (input: unknown) => 
  pipe(
    type.decode(input),
    map(validated => {
      // 只保留类型中声明的属性
      const allowedKeys = Object.keys(type.props);
      return Object.fromEntries(
        allowedKeys.map(key => [key, (validated as any)[key]])
      ) as T;
    })
  );

// 使用示例
const Request = t.type({
  id: t.string,
  name: t.string
});

const r = strictDecode(Request)(req);

if (isLeft(r)) {
  console.log(PathReporter.report(r));
} else {
  const filteredKeys = Object.keys(r.right);
  const inputKeys = Object.keys(req);
  // 对比属性数量,不一致则说明有多余属性
  if (filteredKeys.length !== inputKeys.length) {
    const extraProps = inputKeys.filter(k => !filteredKeys.includes(k)).join(', ');
    console.log(`存在未声明的属性:${extraProps}`);
  } else {
    console.log("validate success");
  }
}

内容的提问来源于stack exchange,提问作者Colin Han

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 18:31:49