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
相关产品推荐
相关产品推荐

