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

TypeScript:扩展数组元素函数的类型校验异常排查

问题:TypeScript数组元素扩展函数的类型错误排查

我尝试编写一个TypeScript函数,为数组中的每个元素执行回调函数并扩展新属性,具体代码如下:

interface Row {
    a: number
}
export function extender<
  Data extends Row[],
  T extends object,
  Props extends keyof T
>(data: Data, extend: (row: Row) => T, newProp?: Props): (T & Row)[] {
    return data.map(row => ({
        ...row,
        ...extend(row)
    }))
}

当调用时不使用回调的row参数,代码可以正常运行:

extender([{ a: 1 }, { a: 2 }], () => ({ once: 1, more: 2 }), 'once')

但当在回调中使用row参数时,会出现类型错误:Argument of type '"once"' is not assignable to parameter of type 'undefined',具体调用代码如下:

// TS_ERROR: Argument of type '"once"' is not assignable to parameter of type 'undefined'.
extender([{ a: 1 }, { a: 2 }], (row) => ({ once: 1, more: row.a * 2 }), 'once')

请问忽略了什么细节导致该错误?


原因与解决方案

问题出在TypeScript的类型推断逻辑上:

  • 当回调不使用row参数时,TS能直接推断出T是具体的对象类型{ once: number; more: number },因此keyof T是"once" | "more",newProp参数可以正常接收"once"。
  • 当回调使用row参数时,TS会错误地将T推断为依赖于row参数的泛型类型(而非具体对象类型),导致keyof T被解析为never,此时newProp的类型就变成了undefined,自然无法传入"once"。

修正方案

移除多余的Data extends Row[]泛型参数,让T仅代表回调返回的具体对象类型,同时让回调参数与输入数组的元素类型绑定:

interface Row {
    a: number
}
export function extender<
  T extends object,
  Props extends keyof T
>(data: Row[], extend: (row: Row) => T, newProp?: Props): (T & Row)[] {
    return data.map(row => ({
        ...row,
        ...extend(row)
    }))
}

如果需要支持Row的子类型数组(保留输入数组的具体类型),可以调整为:

interface Row {
    a: number
}
export function extender<
  R extends Row,
  T extends object,
  Props extends keyof T
>(data: R[], extend: (row: R) => T, newProp?: Props): (R & T)[] {
    return data.map(row => ({
        ...row,
        ...extend(row)
    }))
}

修正后再调用包含row参数的回调,类型检查就能正常通过了。


内容的提问来源于stack exchange,提问作者yurk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 19:27:30