TypeScript中如何用类型约束Record的回调参数匹配对应Payload
TypeScript 事件回调参数的精准类型匹配问题
问题描述
给定以下TypeScript事件类型定义:
export type AnalyticsEventButtonClicked = { type: 'AnalyticsEventButtonClicked', payload: { label: string; } }; export type AnalyticsEventTextChanged = { type: 'AnalyticsEventTextChanged', payload: { value: string; } }; export type AnalyticsEvents = | AnalyticsEventButtonClicked | AnalyticsEventTextChanged;
需要创建handleAnalytics对象,要求每个键对应的回调函数参数严格匹配对应事件类型的payload。现有示例代码中???位置需要替换为合适类型,以确保类型安全:
export const handleAnalytics: Record<AnalyticsEvents['type'], (???['payload']) => string> = { AnalyticsEventButtonClicked: ({ label }) => { return `Label: ${label}`; }, AnalyticsEventTextChanged: ({ value }) => { return `Value: ${value}`; }, };
解决方案
直接用Record泛型无法实现每个键对应独立的参数类型,需要结合映射类型和Extract工具类型来完成精准的类型映射。
完整实现代码
export const handleAnalytics: { [T in AnalyticsEvents['type']]: (payload: Extract<AnalyticsEvents, { type: T }>['payload']) => string } = { AnalyticsEventButtonClicked: ({ label }) => `Label: ${label}`, AnalyticsEventTextChanged: ({ value }) => `Value: ${value}`, };
类型逻辑解释
[T in AnalyticsEvents['type']]:遍历AnalyticsEvents所有可能的type值,作为对象的键。Extract<AnalyticsEvents, { type: T }>:从AnalyticsEvents联合类型中,筛选出type属性等于当前遍历值T的具体事件类型。Extract<...>['payload']:提取该具体事件类型的payload属性,作为对应回调函数的参数类型。
这样每个回调的参数都会精准匹配对应事件的payload结构,TypeScript会自动校验参数合法性——比如在AnalyticsEventButtonClicked的回调中访问value属性会直接抛出类型错误。
可选:封装复用工具类型
如果需要多次复用该类型逻辑,可以先封装工具类型:
// 根据事件type获取对应payload类型的工具类型 type EventPayload<T extends AnalyticsEvents['type']> = Extract<AnalyticsEvents, { type: T }>['payload']; // 使用工具类型定义handleAnalytics export const handleAnalytics: { [T in AnalyticsEvents['type']]: (payload: EventPayload<T>) => string } = { AnalyticsEventButtonClicked: ({ label }) => `Label: ${label}`, AnalyticsEventTextChanged: ({ value }) => `Value: ${value}`, };
内容的提问来源于stack exchange,提问作者bashaus
相关产品推荐
相关产品推荐

