打字稿相同类型的多个泛型

时间:2018-04-12 11:10:16

标签: typescript generics

我有很多需要传递给地图的列表所以我决定创建一个listToMap函数:

export function listToMap<T>(
  list: T[],
  keyAccesFn: (listElement: T) => string): Map<string, T> {
  const reducer = (accumulator: Map<string, T>, currentValue: T) => accumulator.set(keyAccesFn(currentValue), currentValue);
  return list.reduce(reducer, new Map<string, T>());
};

该函数接受一个列表和一个返回列表元素字符串的函数。结果是一个Map,返回的字符串keyAccesFn作为该函数使用的侦听器的键。

现在我发现我不仅需要提取列出的对象的地图键,而且还要提取值本身。我决定通过将另一个函数传递给listToMap函数来解决这个问题,该函数可能返回一个新的Type。该函数看起来像这个atm:

export function listToMap2<T1, T2>(
  list: T1[],
  keyAccesFn: (element: T1) => string,
  valueAccesFn: (element: T1) => T2 = (element: T1) => element): Map<string, T2> {
  const reducer = (accumulator: Map<string, T2>, currentValue: T1) => accumulator.set(keyAccesFn(currentValue), valueAccesFn(currentValue));
  return list.reduce(reducer, new Map<string, T2>());
};

问题是:我想提供一个默认的valueAccessFn,只返回列表元素,这样我可以用listToMap2替换listToMap,但不能像打字稿一样不接受泛型类型T1可能是泛型类型T2。这让我特别恼火,因为我没有其他地方通过T2的任何事情。

1 个答案:

答案 0 :(得分:2)

您指定的默认值存在两个问题:

  1. 当您调用该函数时,Typescript将不会使用默认值进行推理,因此即使您可以设置默认值,它也不会推断T1=T2
  2. 由于T1T2是不同的类型,因此根据方法定义,它无法判断T1是否与T2兼容
  3. 这两个问题都可以解决,第一个是通过为T1指定默认值,第二个是通过对任何默认值使用类型断言来解决。

    export function listToMap2<T1, T2 = T1>(
        list: T1[],
        keyAccesFn: (element: T1) => string,
        valueAccesFn: ((element: T1) => T2) = ((element: T1) => element) as any): Map<string, T2> {
        const reducer = (accumulator: Map<string, T2>, currentValue: T1) => accumulator.set(keyAccesFn(currentValue), valueAccesFn(currentValue));
        return list.reduce(reducer, new Map<string, T2>());
    };
    
    listToMap2([''], k=> k) // Map<string, string>
    listToMap2([''], k=> k, k=> k.length); //Map<string, number>