如何声明可接受联合类型内任意类型的TypeScript Record类型?
报错原因
你原先写的Handler类型是泛型函数类型,约束的是「每个被赋值给Handler的函数,必须能接收所有符合extends Option的入参」,也就是不管是OptionA还是OptionB,这个函数都得能处理。但你给a、b属性赋值的函数分别只接收OptionA、OptionB,不满足「能处理所有Option子类型」的要求,和函数参数的逆变检查规则冲突,所以会报类型错误。
正确写法
把泛型定义从函数层面挪到类型映射层面,基于Option的判别式type自动匹配每个key对应的入参类型即可:
type OptionA = { type: 'a' }; type OptionB = { type: 'b' }; type Option = OptionA | OptionB; type Handlers = { [K in Option['type']]?: (option: Extract<Option, { type: K }>) => boolean; }; const handlers: Handlers = { a: (x) => !!x, // x自动推导为OptionA,无需手动标注类型 b: (x) => !!x, // x自动推导为OptionB };
写法说明
- 映射类型
[K in Option['type']]会遍历Option联合里所有type字段的值(也就是'a' | 'b')作为Handlers的合法key,后面的?对应原写法里Partial的效果,支持只声明部分处理函数 Extract<Option, { type: K }>会从Option联合类型中筛选出type值匹配当前K的成员,作为对应key下处理函数的入参类型,自动获得精准类型提示- 如果你需要支持任意字符串作为key,同时对
a/b这类和type重名的key做严格类型校验,可以把Handlers定义成交叉类型:
type Handlers = { [K in Option['type']]?: (option: Extract<Option, { type: K }>) => boolean; } & Record<string, (option: Option) => boolean>;
这种写法下,非a/b的自定义key对应的处理函数,只要能接收完整的Option联合类型作为入参就符合类型要求。
内容的提问来源于stack exchange,提问作者Irene
相关产品推荐
相关产品推荐

