为何类型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
相关产品推荐
相关产品推荐

