#typescript
Вопрос:
Я пытаюсь немного лучше ввести свою pick
функцию, вот что у меня есть:
export function pick<T, K extends keyof T>(obj: T, keys: K[]): Partial<T> {
const ret = Object.create(null)
for(const key of keys) {
ret[key] = obj[key]
}
return ret
}
Вот чего я хочу:
export function pick<T, K extends keyof T>(obj: T, keys: K[]): K is keyof T ? T : Partial<T>
т. е. если я передам все ключи T
, то я хочу, чтобы TypeScript знал, что он вернет полное T
. Если я передам подмножество ключей, это вернет a Partial<T>
(или, еще лучше, что-то в том смысле, что если K находится в T, то T[K] еще undefined
).
Могу ли я это сделать? Похоже, я могу выполнять только extends
условные обозначения, а не условные обозначения «точно есть».
Или, может быть, я могу сделать возвращаемый тип чем-то вроде {[K in keyof T]: T[K]}
, но я не знаю, как отрицать in keyof
, чтобы указать, что остальные ключи будут undefined
Pick<>
Помощник здесь не работает, потому что моя реализация немного отличается-я не возвращаю объект из пересечения ключей, он всегда будет возвращать именно K
ключи.
Ответ №1:
Поскольку вы требуете K extends keyof T
, точное равенство этих двух типов было бы эквивалентно обратной границе — keyof T extends K
:
export function pick<T, K extends keyof T>(obj: T, keys: K[]): keyof T extends K ? T : Partial<T> {
const ret = Object.create(null)
for(const key of keys) {
ret[key] = obj[key]
}
return ret
}
interface Vals { key1: number, key2: number };
const full: Vals = pick({key1: 1, key2: 2}, ['key1', 'key2']);
const partial: Partial<Vals> = pick({key1: 1, key2: 2}, ['key1']);