将类型指定为某些字符串文字

时间:2018-01-31 19:57:57

标签: typescript typescript-typings

我想说我想要创建一个类似于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}

键入objvalue很简单:

function assignKey<O, V>(obj: O, key, value: V)

但是我在向key提供类型时遇到了麻烦,因此它可以保持输入的准确性。

如果我将其键入string,那么当它实际上是字符串文字时,我会丢失粒度。我希望将其键入K extends stringkey: K可能能够表示它可以是字符串文字或字符串,但这似乎不是这样。

所以我的问题是,是否有任何方法可以将key键入为字符串文字或类型为string,以便生成的输出可以像可能吗

1 个答案:

答案 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>

希望有所帮助!