为什么 "prop" 的这个 TS 实现可以工作,而我的却不行?

Why does this TS implementation of "prop" work but mine does not?

我正在浏览一些关于如何使用打字稿的 keyof 功能来实现 Ramda/Underscore 中称为 prop 的经典函数的博客,其中 returns 对应的值到某个对象上的给定键。

示例:

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

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

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; }

Playground


O extends Record<K, any> 约束阻止传递没有 K 属性

的对象