检查http服务针对typescript接口返回的对象的结构

时间:2018-02-03 13:31:47

标签: javascript typescript

我想检查http JSON响应的内容/结构是否确实与typescript接口/类型匹配。这是针对正在运行的后端的javascript集成测试的上下文。

例如,我们的一个打字稿界面如下:

export interface CurrentUser {
  id: number;
  firstname: string;
  lastname: string;
  roles: string[];
}

如果后端返回一个包含age属性且没有firstname属性的对象,那么我想在运行时以某种方式通知返回对象的结构不同而且测试会失败

另外,我想避免为每个字段手动编码检查/断言。

我理解运行时不再存在typescript接口。那我怎么能依靠打字稿进行这样的检查呢?

如果使用打字稿不可能,那么什么是替代(库,模式)?

1 个答案:

答案 0 :(得分:1)

没有 native 方法直接使用typescript接口来执行运行时类型断言。您应该创建自己的javascript实现。

(i)有unofficial TS compiler允许自动执行此过程。

  

另外,我想避免为每个字段手动编码检查/断言。

不幸的是,除非您决定使用自定义编译器等解决方案,否则您将不得不这样做。例如,您可以测试这样的对象:

const isValidUser = (object) => {
    if ('object' !== typeof object) return false;

    const { id, firstname, lastname, roles } = object;
    
    return typeof id === 'number'
        && typeof firstname === 'string'
        && typeof lastname === 'string'
        && Array.isArray(roles)
        && roles.reduce((acc, value) => acc && typeof value === 'string', true);
}

// prints false (missing lastname property)
document.body.innerText = isValidUser({
    id: 1,
    firstname: 'John',
    roles: ['admin', 'content-editor'],
});

上面的示例对所有属性(在线状态和类型)执行所有基本检查。此外,您可以使用LodashRamda等库来清理类型检查语法,并使事情更容易理解(和维护)。一个例子:

const { all, allPass, pipe, prop } = R;
const { isArray, isNumber, isObject, isString } = _;

const isValidUser = allPass([
    isObject,
    pipe(prop('id'), isNumber),
    pipe(prop('firstname'), isString),
    pipe(prop('lastname'), isString),
    pipe(prop('roles'), isArray),
    pipe(prop('roles'), all(isString)),
]);

// prints false (missing lastname property)
document.body.innerText = isValidUser({
    id: 1,
    firstname: 'John',
    roles: ['admin', 'content-editor'],
});
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.4/lodash.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>