TypeScript判别联合类型与泛型兼容问题及优化方案咨询
问题:TypeScript Result类型复用ok/err函数时的类型不兼容问题
背景代码
我使用TypeScript 5.4.5,定义了以下工具类型与函数:
type Result<T, E> = [T, null] | [null, E]; function ok<T>(good: T): Result<T, null> { return [good, null]; } function err<E>(bad: E): Result<null, E> { return [null, bad]; }
有一个使用Result类型处理fetch响应的工具函数可正常编译:
type FetchResult = Result<Response, Error>; async function tryFetch(fetch: () => Promise<Response>): Promise<FetchResult> { try { const result = await fetch(); if (!result.ok) { return [null, new Error(`Failed to fetch: ${result.statusText}`)]; } return [result, null]; } catch (error) { return [null, error as Error]; } }
但复用该类型系统的tryFetchJson函数出现TypeScript错误:
type FetchJsonResult<T> = Result<T, Error>; async function tryFetchJson<T>(fetchFn: () => Promise<Response>): Promise<FetchJsonResult<T>> { try { const response = await fetchFn(); if (!response.ok) { return err(new Error(`Failed to fetch: ${response.statusText}`)); } const data: T = await response.json(); return ok(data); } catch (error) { return err(error as Error); } }
错误信息
类型 'Result<null, Error>' 无法赋值给类型 'FetchJsonResult<T>'。 类型 '[null, null]' 无法赋值给类型 'FetchJsonResult<T>'。 类型 '[null, null]' 无法赋值给类型 '[T, null]'。 源类型第0位与目标类型第0位不兼容。 类型 'null' 无法赋值给类型 'T'。 'T' 可被实例化为任意与 'null' 无关的类型。
类型 'Result<T, null>' 无法赋值给类型 'FetchJsonResult<T>'。 类型 '[null, null]' 无法赋值给类型 'FetchJsonResult<T>'。
类型 'Result<null, Error>' 无法赋值给类型 'FetchJsonResult<T>'。
解决方案
问题根源在于ok和err函数返回的是整个Result联合类型,包含了不符合目标类型的分支(比如ok返回的Result<T, null>包含[null, null]分支,而FetchJsonResult<T>的错误分支是[null, Error])。只需修改ok和err函数,让它们返回具体的元组分支而非整个联合类型,就能让TypeScript正确识别返回值匹配目标类型:
type Result<T, E> = [T, null] | [null, E]; // 修改为返回具体的成功元组分支 function ok<T>(good: T): [T, null] { return [good, null]; } // 修改为返回具体的错误元组分支 function err<E>(bad: E): [null, E] { return [null, bad]; }
修改后,tryFetchJson函数无需任何类型断言即可正常编译:
ok(data)返回的[T, null]是FetchJsonResult<T>的合法分支err(...)返回的[null, Error]也是FetchJsonResult<T>的合法分支
TypeScript能直接确认这两个返回值都属于目标联合类型的一部分,因此不会再抛出类型不兼容错误。
内容的提问来源于stack exchange,提问作者andersra
相关产品推荐
相关产品推荐

