在元组中使用映射类型

时间:2019-05-04 12:44:19

标签: typescript

我该如何在TypeScript中输入

function arrayToObject(array, mapper) {
    const result = {};
    for(const item of array) {
        const [key, value] = mapper(item);
        result[key] = value;
    }
    return result;
}

// returns { '1': 2, '2': 4, '3': 6 }
arrayToObject([1,2,3], v => [v, v * 2])

具体来说,我想让TypeScript确保来自映射器的元组结果是有效的键和值。这不起作用:

function arrayToObject<TItem, TObject>(
    array: TItem[],
    mapper: (t: TItem) => [P in keyof TObject, TObject[P]]
)

1 个答案:

答案 0 :(得分:3)

假设使用TS3.4并使用const assertions(可以更改该技术以支持TS3.3,并且不需要这样的断言,但这很乏味),我能想到的最强类型是:

function arrayToObject<A, K extends keyof any, V>
  (array: readonly A[], mapper: (x: A) => readonly [K, V]): { [P in K]: V } {
  const result = {} as { [P in K]: V };
  for (const item of array) {
    const [key, value] = mapper(item);
    result[key] = value;
  }
  return result;
}

const obj1 = arrayToObject([1, 2, 3] as const, v => [v, v * 2] as const)
// const obj1: {1: number, 2: number, 3: number}

const obj2 = arrayToObject(["a", "b", "c"] as const, k => [k, 0] as const);
// const obj2: {a: 0, b: 0, c: 0}

这将至少保留编译器在映射器的返回类型中知道的所有文字键值。除了某些特定的higher rank types之外,类型系统对generic function improvements的支持不多,因此我很难想到编译器可以理解的任何方式,例如

const obj3 = arrayToObject(["a","b","c"] as const, k => [k, k] as const)

最终将以{a: "a", b: "b", c: "c"}类型而不是仍然正确但不是很特定的类型{a: "a"|"b"|"c", b: "a"|"b"|"c", c: "a"|"b"|"c"}结束。哦,很好。

希望有所帮助;祝你好运!