1

我正在尝试解析返回用户数组的 API 响应。我发现即使数组中的一个元素验证失败,整个编解码器也会返回错误。我希望错误留在数组中,这样我就可以有类似Array<Either<E, User>>. 我的 API 的响应看起来像这样

{
    "success": true,
    "result": [
        {
            "name": "Jo Smith",
            "email": "jo@jo.jo",
            "preferredName": null
        },
        {
            "name": "Robert",
            "email": "rob@rob.rob",
            "preferredName": "Rob"
        }
    ]
}

或者

{
    "success": false,
    "error": "Something went wrong"
}

所以这是我的编解码器

import * as t from "io-ts";

const userV = t.type({
    name: t.string,
    email: t.string,
    preferredName: t.union([t.string, null]),
});

const successV = t.type({
    success: t.literal(true),
    result: t.array(userV),
});

const errorV = t.type({
    success: t.literal(false),
    error: t.string,
});

const responseV = t.union([successV, errorV]);

现在,如果由于某种原因,我们收到一个电子邮件为 null 的用户,则整个响应都会失败。如果我想列出正确解析的用户并在我的 UI 中仅为错误用户显示错误消息怎么办?显而易见的(天真的?)方法是使所有属性都可以为空,但有更好的方法吗?我还考虑过先返回 a 分两步解析响应,t.array(t.unknown)但我不确定这会是什么样子

4

1 回答 1

1

你可以:

import * as t from "io-ts";
import * as F from 'fp-ts/function'
import * as E from 'fp-ts/Either'
import * as A from 'fp-ts/Array'

const users: unknown[] = [{
  name: 'badUser',
  email: null,
  preferredName: 'hey'
}, {
  name: 'goodUser',
  email: 'ihaveemail@mail.com',
  preferredName: 'okay'
}]

const result = F.pipe(
  users,
  A.map(userV.decode),
  A.separate
)

A.separate是一个函数,它接受一个Array<Either<A, B>>并返回一个对象,其中所有的Lefts 都在left字段中,而Rights 在right字段中。

于 2021-07-16T11:57:45.383 回答