简体   繁体   English

为什么这个“prop”的 TS 实现有效,而我的却没有?

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

I was looking through some blogs about how to use the keyof feature of typescript to implement a classic function in Ramda/Underscore called prop which returns the value corresponding to a given key on a certain object.我正在浏览一些关于如何使用keyof功能在keyof中实现一个名为prop的经典函数的博客,该函数返回与某个对象上的给定键对应的值。

Example:例子:

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

I ended up with this implementation (similar to underscore's) that does work:我最终得到了这个确实有效的实现(类似于下划线):

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

But when I change it to a curried version:但是当我将其更改为咖喱版本时:

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

I get an error when I try to invoke it as prop('someProp')(someObj) ;当我尝试将其作为prop('someProp')(someObj)调用时出现错误; as I hover over prop I get an error that says Argument of type 'someProp' is not assignable to parameter of type 'never' and I really don't know why.当我将鼠标悬停在prop我收到一条错误消息,指出Argument of type 'someProp' is not assignable to parameter of type 'never'我真的不知道为什么。

How can I go about this?我该怎么办?

UPDATE : Solved!更新:解决了! And now these tests pass:现在这些测试通过了:

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

Oh man, I didn't know Record and PropertyKey existed...哦,伙计,我不知道 Record 和 PropertyKey 存在...

You need to move object's generic parameter to the second function (where object is provided as a function's parameter):您需要将对象的通用参数移动到第二个函数(其中对象作为函数的参数提供):

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> constraint prevents passing objects that don't have K property O extends Record<K, any>约束阻止传递没有K属性的对象

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM