【发布时间】:2020-03-26 04:51:57
【问题描述】:
我今天正在研究一种从两个字符串列表创建键值映射的方法。这是一个例子:
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中此代码的链接
【问题讨论】: