缩小泛型类型,即 keyof 类型而不指定泛型参数

Psy*_*nic 3 typescript

如果这在某个地方重复,我深表歉意,我的谷歌无法找到正确的单词来缩小结果范围。

我正在尝试创建一个辅助函数来重用某些功能,但无法完全弄清楚是否/如何实现它。

给定一个带有泛型的函数(或类型),其中一个参数是指定泛型类型的键,函数返回类型被确定为泛型类型上特定属性的返回类型,而不是每个属性类型的并集关于泛型类型。

interface MyObject {
  readonly foo: Date;
  readonly bar: number;
  readonly wizz: string;
  readonly bang: boolean;
}

function getHelpers<ItemType>(key: keyof ItemType) {
  return (item: ItemType) => item[key];
}

const res = getHelpers<MyObject>('bang');
// Has type of `(item: MyObject) => string | number | boolean | Date`, when I need it to have `(item: MyObject) => boolean`
Run Code Online (Sandbox Code Playgroud)

我知道如果我添加一个辅助泛型参数来缩小键类型,那么它就可以工作:

function getHelpers<ItemType, KeyType extends keyof ItemType>(key: KeyType) {
  return (item: ItemType) => item[key];
}

const res = getHelpers<MyObject, 'bang'>('bang'); // Has typed of `(item: MyObject) => boolean`

Run Code Online (Sandbox Code Playgroud)

但如果可能的话,我宁愿不必在每次调用函数时都指定通用参数来重复密钥。

Tit*_*mir 5

interface MyObject {
    readonly foo: Date;
    readonly bar: number;
    readonly wizz: string;
    readonly bang: boolean;
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,如果没有函数柯里化,这是不可能的。您的第二个选择是正确的方法。理想情况下,我们希望指定ItemType但推断KeyType。不幸的是这是不可能的。我们要么推断所有类型参数,要么必须指定所有类型参数。有一个支持部分推理的功能提案,但已被推迟数次,目前不在路线图上。

解决方案是使用两个函数调用,我们指定第一个函数调用ItemType,并让第二个调用进行推理。

function getHelpers<ItemType>() {
    return function <KeyType extends keyof ItemType>(key: KeyType) {
        return (item: ItemType) => item[key];
    }
}

const res = getHelpers<MyObject>()('bang'); // Has typed of `(item: MyObject) => boolean`
Run Code Online (Sandbox Code Playgroud)