如何让TypeScript自动推断handle函数泛型类型无需显式声明
解决TypeScript泛型自动推断问题:关联版本键与处理函数的类型匹配
问题核心
当前handle函数必须显式指定OtherProps和Result泛型才能正常工作,根源在于:
- 原
Handlers类型强制所有处理函数返回统一的Result,且OtherProps全局一致,无法适配不同处理函数返回不同类型的场景(比如multipliers中alpha返回string、beta返回number)。 execute回调的泛型约束过于宽泛,TypeScript无法将props.value的类型与对应handler的value参数类型关联起来。
解决方案
通过重构类型定义和handle函数的泛型结构,让TypeScript自动从处理函数字典中推断公共OtherProps和每个键对应的返回类型:
1. 重构类型定义
调整Handler和Handlers的定义,保留每个键对应的返回类型,同时提取公共的OtherProps:
export interface VersionDictionary { alpha: string beta: number } export type VersionKey = keyof VersionDictionary // 单个处理函数:保留Key对应的value类型与自定义返回类型 export type Handler<Key extends VersionKey, OtherProps, Result> = ( props: OtherProps & { value: VersionDictionary[Key] } ) => Result // 处理函数字典:每个Key对应独立的Handler类型,允许不同返回值 export type Handlers<OtherProps, ResultMap extends Record<VersionKey, unknown>> = { [Key in VersionKey]: Handler<Key, OtherProps, ResultMap[Key]> } export interface Matched<Key extends VersionKey, OtherProps, Result> { handler: Handler<Key, OtherProps, Result> value: VersionDictionary[Key] }
2. 修改match和handle函数泛型
调整泛型参数,适配不同返回类型,让TypeScript自动推断类型:
function match<OtherProps, Key extends VersionKey, Result>( data: Partial<VersionDictionary>, handlers: Handlers<OtherProps, Record<VersionKey, Result>>, key: Key ): Matched<Key, OtherProps, Result> | undefined { const value = data[key] if (value == null) return undefined const handler = handlers[key] return { handler, value } } // 通过ResultMap捕获每个Key的返回类型,自动推断OtherProps function handle<OtherProps, ResultMap extends Record<VersionKey, unknown>>( dictionary: Partial<VersionDictionary>, handlers: Handlers<OtherProps, ResultMap>, execute: <Key extends VersionKey>( props: { value: VersionDictionary[Key] handler: Handler<Key, OtherProps, ResultMap[Key]> } ) => ResultMap[Key] ): ResultMap[keyof ResultMap] { let key: VersionKey for (key in handlers) { const matched = match(dictionary, handlers as Handlers<OtherProps, Record<VersionKey, ResultMap[typeof key]>>, key) if (matched == null) continue return execute({ value: matched.value, handler: matched.handler }) } throw new Error('Unknown key') }
3. 验证示例代码
现在无需显式指定泛型,TypeScript能自动推断类型且无报错:
const alphaData = { alpha: 'hello' } const betaData = { beta: 4 } const labelers = { alpha: (props: { value: string, label: string }) => `${props.label}: ${props.value}`, beta: (props: { value: number, label: string }) => `${props.label} + 1: ${props.value + 1}` } const label = `Test (${new Date().toISOString()})` // 自动推断OtherProps为{ label: string },Result为string handle(alphaData, labelers, (props) => props.handler({ value: props.value, label })) handle(betaData, labelers, (props) => props.handler({ value: props.value, label })) const multipliers = { alpha: (props: { value: string, count: number }) => props.value.repeat(props.count), beta: (props: { value: number, count: number }) => props.value * props.count } const count = 5 // 自动推断OtherProps为{ count: number },Result为string | number handle(alphaData, multipliers, (props) => props.handler({ value: props.value, count })) handle(betaData, multipliers, (props) => props.handler({ value: props.value, count }))
关键改动说明
Handlers类型重构:新增ResultMap泛型,允许每个版本键对应不同返回类型,打破原定义中所有处理函数返回同类型的限制。handle函数泛型调整:通过ResultMap捕获每个键的返回类型,让TypeScript自动从处理函数字典推断公共OtherProps和各键返回值类型。execute回调约束强化:明确handler返回类型为ResultMap[Key],确保props.value与handler的value参数类型严格匹配,解决类型不兼容错误。
内容的提问来源于stack exchange,提问作者David Y. Stephenson
相关产品推荐
相关产品推荐

