Почему эта реализация TS "prop" работает, а моя нет? - PullRequest
1 голос
/ 14 марта 2020

Я просматривал некоторые блоги о том, как использовать функцию keyof машинописного текста для реализации функции c classi в Ramda / Underscore с именем prop, которая возвращает значение, соответствующее данному ключу для определенного объекта.

Пример:

prop('length')('hello'); //> 5 | Ramda's curried implementation
prop('length', 'hello'); //> 5 | Underscore and others

Я закончил с этой реализацией (похожей на подчеркивание), которая работает:

export function prop<O, K extends keyof O>(key: K, obj: O): O[K] {
  return obj[key];
}

Но когда я изменил ее на версию с карри :

export function prop<O, K extends keyof O>(key: K) {
  return function prop__(obj: O): O[K] {
    return obj[key];
  }
}

Я получаю сообщение об ошибке при попытке вызвать его как prop('someProp')(someObj); при наведении курсора на prop появляется сообщение об ошибке Argument of type 'someProp' is not assignable to parameter of type 'never', и я действительно не знаю, почему.

Как я могу go об этом?

ОБНОВЛЕНИЕ : решено! И вот эти тесты проходят:

describe('prop', () => {
  test('should obtain prop value from JSON object', () => {
    const author = { name: 'Luis', age: 25 };
    const getAge = prop('age');

    expect(getAge(author)).toBe(25);
  });

  test('should obtain prop value from known data type', () => {
    expect(prop('length')('lovecraft')).toBe(9);
  });
});

О, боже, я не знал, что существуют Record и PropertyKey ...

1 Ответ

3 голосов
/ 14 марта 2020

Вам необходимо переместить универсальный параметр c объекта во вторую функцию (где объект предоставляется в качестве параметра функции):

export function prop<K extends PropertyKey>(key: K) {
    return <O extends Record<K, any>>(obj: O): O[K] => obj[key];
}

const someObj = { someProp: 'a' };

const someProp = prop('someProp')(someObj) // someProp is string

// Expect error
const someProp1 = prop('someProp1')(someObj) // Property 'someProp1' is missing in type '{ someProp: string; }

Детская площадка


O extends Record<K, any> ограничение предотвращает передачу объектов, которые не имеют K свойства

...