Нужны два type parameter: T — форма объекта, K extends keyof T — union ключей. Return — Pick<T, K> или mapped { [P in K]: T[P] }. Тогда pick(user, 'name') вернёт { name: string }, а 'nope' не скомпилируется.
Разбор
K extends keyof T — keys только из реальных свойств T.
Overload или rest tuple (keys: readonly K[]) — для нескольких ключей сразу.
Альтернатива — indexed access T[K] для одного ключа.
Без constraint получите string keys и потеряете проверку.
Пример
function pick<T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K> {
const result = {} asPick<T, K>;
for (const k of keys) result[k] = obj[k];
return result;
}
const user = { id: 1, name: 'Ada', email: 'a@x.dev' };
const partial = pick(user, 'name', 'email');
// { name: string; email: string }// pick(user, 'nope'); // Error
Итог
Точный pick — K extends keyof T + Pick<T,K>; это канонический пример, где generics связывают объект, ключи и форму результата.
Как типизировать generic `pick(obj, keys)`, чтобы результат был точ… · Sobeso