You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 04:35:26