1

我正在浏览一些关于如何使用 typescript 的keyof特性来实现 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'我真的不知道为什么。

我该怎么办?

更新:解决了!现在这些测试通过了:

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 存在...

4

1 回答 1

3

您需要将对象的通用参数移动到第二个函数(其中对象作为函数的参数提供):

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属性的对象

于 2020-03-14T07:42:19.647 回答