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

为何类型P无法从传入键数组推断?调用foo<User>(...)报错

问题原因与解决办法

报错“Expected 2 type arguments, but got 1”的原因

TypeScript 泛型函数的规则是:当你显式指定部分泛型参数时,除非未指定的参数有默认类型,否则必须显式传入所有泛型参数。你的foo函数定义了两个泛型参数<T extends object, P extends keyof T>,且都没有默认值,所以当你只传入User作为T的类型参数时,TypeScript 会要求你同时指定P的类型,否则就会抛出这个错误。

P无法自动推断的原因

同样是因为你显式指定了T的类型参数,TypeScript 的泛型推断逻辑会被打断——它不会再尝试从传入的pick_keys参数中自动推断P的类型,而是要求你显式提供。

解决方案

方案1:让 TypeScript 自动推断所有泛型参数

去掉显式的User类型参数,让 TypeScript 从payload和pick_keys中自动推断T和P:

const {} = foo({ name: 'hh', id: 33 }, ['name', 'id']);
// T 会被推断为 User,P 会被推断为 'name' | 'id'

方案2:给泛型参数P添加默认类型

修改函数定义,给P设置默认类型为keyof T,这样当你显式指定T时,可以省略P的类型参数,TypeScript 会自动从pick_keys推断P:

export const foo = <T extends object, P extends keyof T = keyof T>(payload: User, pick_keys: P[]) => {
    const result = pick(payload, ['email', 'gender']) as T;
    return pick(result, pick_keys);
};

// 现在可以正常调用,P 会从 ['name','id'] 推断为 'name' | 'id'
const {} = foo<User>({ name: 'hh', id: 33 }, ['name', 'id']);

方案3:显式指定两个泛型参数

如果你确实需要显式指定T,可以同时显式指定P的类型:

const {} = foo<User, 'name' | 'id'>({ name: 'hh', id: 33 }, ['name', 'id']);

另外,你的函数里还有一个潜在问题:pick(payload, ['email', 'gender']) as T的类型断言比较危险,如果T不是User的子集,可能会导致类型不匹配。如果foo函数只处理User类型,建议直接把T固定为User;如果要做通用工具函数,可调整payload的类型为T:

// 更通用的写法,payload 类型为 T,而非固定 User
export const foo = <T extends object, P extends keyof T>(payload: T, pick_keys: P[]) => {
    return pick(payload, pick_keys);
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 00:01:03