Сегодня я работал над методом, который создает карту ключа-значения из двух списков строк. Вот пример:
const keys = ['a', 'b', 'c']
const values = ['x', 'y', 'z']
const map = createMap(keys, values)
/*
{
a: 'x',
b: 'y',
c: 'z'
}
*/
Реализация, на которую я попал, выглядит так:
function createMap<T extends string>(
keys: readonly T[],
values: readonly string[]
): Record<T, string> {
if (keys.length !== values.length) {
throw new Error('Key and Value lists must have same length')
}
return keys.reduce<Record<string, string>>((accumulator, key, index) => {
if (accumulator.hasOwnProperty(key)) {
throw new Error('Keys must be unique')
}
return {
...accumulator,
[key]: values[index]
}
}, {})
}
И это работает, но вывод типа имеет странное свойство
Если параметр key
представляет собой переменную, которая содержит массив строк, результатом будет: Record<string, string>
, но если вы напрямую передадите массив параметру key
, результатом будет: Record<'item1' | 'item2' | 'etc.', string>
. Проверьте код ниже для получения более подробной информации:
const keys = ['a', 'b', 'c']
const values = ['x', 'y', 'z']
const map = createMap(keys, values) // type is Record<string, string>
const map = createMap(['a', 'b', 'c'], values) // type is Record<'a' | 'b' | 'c', string>
Может кто-нибудь объяснить, почему он так себя ведет?
Вот ссылка на этот код в TypeScript Playground