Машинописный текст: Как я могу указать, что K-это именно ключ к T?

#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']);
 

Игровая площадка