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

为何TypeScript无法正确推断Option ADT映射函数的类型?

修复Option类型的Functor map函数类型推断错误

以下是仿fp-ts实现的Option代数数据类型(ADT):

export type Option<A> = Some<A> | None

export interface Some<A> {
  _tag: 'Some'
  value: A
}

export interface None {
  _tag: 'None'
}

export const some = <A>(x: A): Option<A> => 
  ({ _tag: 'Some', value: x })

export const none: Option<never> = 
  { _tag: 'None' }

export const isNone = <A>(x: Option<A>): x is None => 
  x._tag === 'None'

type Match = <A, B>(onNone: () => B, onSome: (a: A) => B)
  => (x: Option<A>) => B
  
const match: Match = (onNone, onSome) => x =>
  isNone(x) ? onNone() : onSome(x.value)

尝试编写Option的Functor映射函数mapOption时,TypeScript无法正确推断类型,错误的mapOption代码如下:

type MapOption = <A, B>(f: (x: A) => B) => (fa: Option<A>) => Option<B>
const mapOption: MapOption = f => fa => match(
  () => none,
  (value) => f(value))(fa)

问题原因

  • match的onSome分支直接返回f(value),但f(value)的类型是B,而我们需要返回的是Option<B>,类型不匹配;
  • none的类型是Option<never>,TypeScript无法自动将其与Option<B>做统一类型推导。

修复方案

核心是让match的两个分支都返回Option<B>类型:

  1. 将onSome分支的f(value)用some包裹,生成Some<B>类型的实例;
  2. 确保none能被TypeScript识别为Option<B>的子类型(Option<never>本身是所有Option<B>的子类型,只要另一个分支类型匹配即可自动推导)。

修复后的mapOption代码:

type MapOption = <A, B>(f: (x: A) => B) => (fa: Option<A>) => Option<B>
const mapOption: MapOption = f => fa => match(
  () => none,
  (value) => some(f(value))
)(fa)

也可以省略MapOption类型定义,让TypeScript自动推导完整类型:

const mapOption = <A, B>(f: (x: A) => B) => (fa: Option<A>): Option<B> => 
  match(
    () => none,
    (value) => some(f(value))
  )(fa)

修改后TypeScript就能正确推断出返回类型为Option<B>,解决类型错误问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 04:13:11