简体   繁体   中英

Using a mapped type in a tuple

How would I type this in 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])

Specifically, I want to have TypeScript make sure that the tuple result from mapper is a valid key and value. This doesn't work:

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

Assuming TS3.4 and using const assertions , (the technique can be altered to support TS3.3 and not require such assertions, but it's tedious), the strongest typing I can come up with is:

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}

That will at least preserve any literal key values the compiler knows about in the return type of the mapper. The type system doesn't have much support for higher rank types outside of some specific generic function improvements so it's hard for me to think of any way for the compiler to understand that, say,

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

will end up as type {a: "a", b: "b", c: "c"} instead of the still-correct-but-not-very-specific type {a: "a"|"b"|"c", b: "a"|"b"|"c", c: "a"|"b"|"c"} . Oh well.

Hope that helps; good luck!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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