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

TypeScript泛型为何可传0个却不能传1个?求解决方案

问题

我定义了如下函数:

const create = <S,D>(
  state: S,
  derivedStateResolver: (s:S) => D
) => {
  return {
    state,
    derived:derivedStateResolver(state)
  }
}

我可以这样调用该函数:

const a = create(
  { count: 0},
  (s) => ({positive: s.count > 0})
);

但无法这样调用:

type B_MyState = { count: null | number};

const b = create<B_MyState>( // TS错误:期望2个类型参数,但只传入1个。
  {count: 1},
  (s) => ({positive: (s.count !== null) && s.count > 0})
);

疑问

为何可以传入0个泛型参数,却不能只传入1个?

需求

我希望保留最后一种调用方式,是否有可行的解决办法?


原因解释

TypeScript泛型函数的规则是:要么完全不显式指定泛型参数,让编译器通过实参自动推断所有类型;要么显式指定所有泛型参数,不支持只传其中一部分。这就是传0个参数时编译器能正常工作(自动推断S和D),但只传1个时会报错的原因——函数声明要求2个类型参数,你只提供了1个,不符合规则。

解决办法

有两种实用方案可以实现你想要的调用方式:

方案1:给第二个泛型参数设置默认类型

给D添加默认类型(比如unknown),这样只传S时D会使用默认值,同时编译器依然能通过derivedStateResolver的返回值推断出D的实际类型:

const create = <S, D = unknown>(
  state: S,
  derivedStateResolver: (s:S) => D
) => {
  return {
    state,
    derived: derivedStateResolver(state)
  }
}

// 正常调用
type B_MyState = { count: null | number};
const b = create<B_MyState>(
  {count: 1},
  (s) => ({positive: (s.count !== null) && s.count > 0})
);

方案2:使用柯里化拆分参数

将函数拆分为两次调用:第一次显式指定S类型,第二次传入参数并让编译器自动推断D:

const create = <S>() => <D>(
  state: S,
  derivedStateResolver: (s:S) => D
) => {
  return {
    state,
    derived: derivedStateResolver(state)
  }
}

// 调用方式
type B_MyState = { count: null | number};
const b = create<B_MyState>()(
  {count: 1},
  (s) => ({positive: (s.count !== null) && s.count > 0})
);

方案1更贴近你原本的调用语法,方案2则更清晰地分离了类型指定和参数传递,可根据需求选择。

内容的提问来源于stack exchange,提问作者Jacopo Marrone - tresorama

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 06:50:45