我想说我想要创建一个类似于assignKey
的函数Object.assign()
,但不是将对象合并在一起,而是需要一个起始对象,一个键和一个值。它返回一个基于原始对象的新对象,其中包含参数键和值。
实现此行为非常简单。在简单的JS中,它看起来像:
function assignKey(obj, key, value) {
return Object.assign({}, obj, {[key]: value});
}
然而,在保持尽可能强类型的时候,我遇到了真正的麻烦。
如果我运行assignKey({}, 'foo', 'bar')
,我希望将结果输入为{ foo: string }
。
如果我运行assignKey({}, Math.random().toString(), 'bar')
,我希望将结果输入为{[x: string]: string}
如果您使用常规Object.assign()
执行相应的操作,您最终会得到这些结果。所以:
Object.assign({}, { 'foo': 'bar' })
提供类型{ 'foo': string }
Object.assign({}, { [Math.random().toString()]: 'bar' })
提供类型{[x: string]: string}
键入obj
和value
很简单:
function assignKey<O, V>(obj: O, key, value: V)
但是我在向key
提供类型时遇到了麻烦,因此它可以保持输入的准确性。
如果我将其键入string
,那么当它实际上是字符串文字时,我会丢失粒度。我希望将其键入K extends string
和key: K
可能能够表示它可以是字符串文字或字符串,但这似乎不是这样。
所以我的问题是,是否有任何方法可以将key
键入为字符串文字或类型为string
,以便生成的输出可以像可能吗
答案 0 :(得分:2)
你几乎可以做你想做的事:
function assignKey<T, K extends string, V>(obj: T, key: K, value: V ): T & Record<K, V> {
return Object.assign({}, obj, {[key]: value} as Record<K,V>);
}
这里的键是K extends string
类型,如果需要,这就是让TypeScript推断文字所需的全部内容。值为V
,返回的类型是Record<K,V>
的交集,标准库中的mapped type,其中键的类型为K
,值为类型为V
。然后你得到:
const example1: {foo: string} = assignKey({}, 'foo', 'bar');
// Record<"foo",string>
const example2: {[k: string]: string} = assignKey({}, Math.random().toString(), 'bar')
// Record<string, string>
希望有所帮助!