什么是结果类型

Rust 和 Swift 中熟悉的 Result 类型,顾名思义,结果它代表
在 TypeScript 中,我使用以下作为实现示例。


export type Result<T = void, E = void> =
  | { ok: true; value: T }
  | { ok: false; error: E }

export const Ok = <T, E>(value: T): Result<T, E> => ({
  ok: true,
  value,
})

export const Err = <T, E>(error: E): Result<T, E> => ({ ok: false, error })

我们如何使用它?

当您想根据错误类型更改处理时,它可以具有良好的兼容性。

例如,在进行登录处理时,假设您要根据用户的请求是否无效或其他与网络相关的情况来使用不同的处理。
如果使用Result类型,可以这样写。

// エラーを区別して出す関数
async function signin(payload: SigninPayload): Promise<Result<SigninResponse, "INVALID_REQUEST" | "UNKNOWN_ERROR">> {
	try {
		const res = await fetch("./login", { method: "POST", body: JSON.stringify(payload) })
		if (res.ok) {
			return Ok(res.json() as SigninResponse)
		}

		if (res.status === 400) {
			return Err("INVALID_REQUEST")
		}
		return Err("UNKNOWN_ERROR")
	} catch {
		return Err("UNKNOWN_ERROR")
	}
}

// SomeComponent.tsx
const SomeComponent = () => {
	const handleSubmit = () => {
		const result = await signin(payload)
		if (result.ok) return

		if (result.error === "INVALID_REQUEST") {
			console.log("パスワードとかが間違っているかも")
		}
		if (result.error === "UNKNOWN_ERROR") {
			console.log("レスポンスがJSONじゃなかったり、ネットワークエラーかも...")
		}
	}

	return <form onSubmit={handleSubmit}>...</form>
}

如果result.oktrue,则可以访问result.value 并接收结果,否则可以访问data.error 并根据该值进行处理。

作为不使用Result类型的常用方法,我认为try catch的catch有错误处理。

try {
    const result = await signin(payload)
} catch (err) {
    if (err instanceof CustomError) {
        console.log("独自のErrorクラス定義してハンドリング")
    }

    if (err instanceof Error) {
        console.log("CustomErrorより前にいると引っかかる")
    }
}

当然,这也是可以的,但我认为存在以下缺点。

  • 由于catch抓取的值是any类型,所以需要使用instanceof CustomError等才能正确类型安全
  • 无法获得 Intellisense 支持。
  • 创建新范围和深度嵌套

另一方面,结果类型是

  • 类型安全
  • 获取 Intellisense 支持
  • 没有深度范围或深度嵌套
  • 分离对返回什么错误的关注

对了,已经有这样的库了,有兴趣的可以考虑介绍一下。
(不过,我个人觉得上面的例子对于目前的情况来说已经足够了。)

如果您愿意,请考虑介绍它。


原创声明:本文系作者授权爱码网发表,未经许可,不得转载;

原文地址:https://www.likecs.com/show-308628016.html

相关文章: