如何让TypeScript对无类型Record函数参数实现自动补全并解决类型报错?
TypeScript错误信息工具的类型校验与自动补全问题
问题背景
我正在开发一个TypeScript错误信息工具,已完成核心功能,但options参数的类型校验、自动补全,以及错误名称的自动补全都存在问题。初始代码如下:
type Definition = { code: number note: (opts: Record<string, unknown>) => string } const errors: Record<string, Definition> = { invalid_form: { code: 3, note: ({ name }) => `Form '${name}' is not valid`, }, invalid_type: { code: 2, note: ({ name, type }) => `Value '${name}' is not '${type}' type`, }, missing_property: { code: 1, note: ({ name }) => `Property '${name}' missing`, }, } type Errors = typeof errors type Name = keyof Errors function findError<N extends Name>(name: N, options: Parameters<Errors[Name]['note']>[0]) { const handler = errors[name] const text = handler.note(options) return new Error(text) } findError('invalid_type', { foo: 'string' }) // 此处传入非法参数foo,本应报错但无提示
当前存在的问题:
- 调用
findError时传入非法参数(如示例中的foo),TypeScript未触发类型错误 - 输入
options的键名前缀n时,无法自动补全name(即使参数类型为unknown,也需要补全提示) invalid_type这类错误名称的自动补全失效,推测是Record<string, Definition>类型限制了键名的具体类型推导
需求
- 实现上述类型校验与自动补全功能
- 避免为每个
note函数的参数单独定义类型(此类函数可能多达数十个,单独定义过于繁琐) - 保留定义
errors时的类型提示(因此使用Record<string, Definition>约束)
尝试过的无效写法
我尝试了多种结合extends与条件推断的写法,但均未解决问题:
写法一
function findError< N extends Name, O extends Parameters<Errors[N]['note']>[0], >( name: N, options: { [P in keyof O]: O[P] }, ) { const handler = errors[name] const text = handler?.note(options) return new Error(text) } findError('invalid_type', { foo: 'array' })
写法二
function findError<N extends Name>( name: N, options: Parameters<Errors[N]['note']>[0] extends infer O ? { [P in keyof O]: O[P] } : never, ) { const handler = errors[name] const text = handler?.note(options) return new Error(text) } findError('invalid_type', { foo: 'array' })
写法三
function findError<N extends Name>( name: N, options: Parameters<Errors[N]['note']>[0] extends infer O ? { [KeyType in keyof O as {} extends Record<KeyType, unknown> ? never : KeyType]: O[KeyType] } : never, ) { const handler = errors[name] const text = handler?.note(options) return new Error(text) } findError('invalid_type', { foo: 'array' })
更新:自动补全实现,但出现新报错
调整findError函数后,错误名称和options的自动补全功能正常了,但函数内部出现了新的类型错误:
function findError<N extends Name>( name: N, options: Parameters<Errors[N]['note']>[0], ) { const handler = errors[name] const text = handler?.note(options) // 此处触发类型报错 return new Error(text) } findError('invalid_form', { name: 'any', type: 'asdf' }) // 自动补全正常,但多余参数type未报错
报错信息:
Argument of type '{ name: any; } | { name: any; type: any; } | { name: any; another: any; }' is not assignable to parameter of type '{ name: any; } & { name: any; type: any; } & { name: any; another: any; }'. Type '{ name: any; }' is not assignable to type '{ name: any; } & { name: any; type: any; } & { name: any; another: any; }'. Property 'type' is missing in type '{ name: any; }' but required in type '{ name: any; type: any; }'.ts(2345)
内容的提问来源于stack exchange,提问作者Lance Pollard
相关产品推荐
相关产品推荐

