在不指定泛型参数的情况下缩小为keyof类型的泛型类型

时间:2019-06-15 10:01:56

标签: typescript

很抱歉,如果某处重复出现该错误,我的Google-fu无法找到正确的词来缩小搜索范围。

我正在尝试创建一个辅助函数以重用某些功能,但是我并不确定是否可以实现它。

给出具有泛型的函数(或类型),其中一个参数是指定泛型类型的键,将函数返回类型确定为泛型上该特定属性的返回类型,而不是通用类型上的每个属性类型。

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`

我知道如果我添加一个辅助通用参数来缩小键类型的范围,那么它将起作用:

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`

但是我宁愿不必在每次调用该函数时都通过指定通用参数来复制键。

1 个答案:

答案 0 :(得分:3)

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

不幸的是,如果不使用函数,这是不可能的。第二种选择是正确的方法。理想情况下,我们希望指定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`