【问题标题】:Dynamic keys in TypescriptTypescript 中的动态键
【发布时间】:2020-07-26 11:38:42
【问题描述】:

我有一些这样的 formData 对象(我在运行时得到它):

const formData = {
  xAxisColumn: 'abc',
  periodColumn: 'cde'
};

以及我从具有下一个结构的服务器获取的数据:

const response = {
  abc: 'some data 1',
  cde: 123,
  otherColumn: 'bla...'
}

我正在 Typescript 中尝试为响应对象创建一个类型,其中键是动态的并且基于 formData 值。

类似:

type TResponse<T, U> = {
 [T]: string;
 [U]: number;
}

但这对于 TS 来说是不正确的,那我该怎么做呢?谢谢。

【问题讨论】:

  • 你在运行时得到这个 ``` xAxisColumn: 'abc',``` 吗?
  • @Drag13 是的,当得到响应时
  • TypeScript 在运行时不存在。你什么都做不了。
  • @Drag13 好的。谢谢

标签: typescript


【解决方案1】:

在不确切知道您的代码的其余部分将如何使用它的情况下,您正在寻找的类型可以这样表示:

type TResponse<KS extends PropertyKey, KN extends PropertyKey> = 
  Record<KS, string> & Record<KN, number>;

这是两个Record 类型中的intersection。它说TResponse&lt;KS, KN&gt;KS 类型的键处有一个string 属性,在KN 类型的键处有一个number 属性。


你可以这样使用它:

const formData = {
  xAxisColumn: 'abc',
  periodColumn: 'cde'
} as const;

const response = {
  abc: 'some data 1',
  cde: 123,
  otherColumn: 'bla...'
}

function processResponse<KS extends PropertyKey, KN extends PropertyKey>(
  formData: { xAxisColumn: KS, periodColumn: KN },
  response: TResponse<KS, KN>
) {
  const xAxis: string = response[formData.xAxisColumn];
  const period: number = response[formData.periodColumn];
  // ... process them here
}

processResponse(formData, response); // okay
processResponse({ xAxisColumn: "x", periodColumn: "p" }, { x: "okay", p: 123 }); // also okay
processResponse({ xAxisColumn: "x", periodColumn: "p" }, { x: 123, p: 456 }); // error!
// number is not assignable to string -------------------> ~

或许

function keyVal<K extends PropertyKey, V>(key: K, val: V) {
  return { [key]: val } as Record<K, V>;
}

function makeResponse<KS extends PropertyKey, KN extends PropertyKey>(
  formData: { xAxisColumn: KS, periodColumn: KN }
): TResponse<KS, KN> {
  return Object.assign(keyVal(formData.xAxisColumn, "x axis data"), keyVal(formData.periodColumn, 123));
}

示例代码的重点是表明,只要编译器知道 literal 的值formData。当KSKN 是已知的文字类型时,您会发现TResponse&lt;KS, KN&gt; 更容易使用。

processResponse() makeResponse()的实现中,KSKN是未指定的泛型类型,编译器对TResponse&lt;KS, KN&gt;的推理变得更加困难,你需要找到迂回的方式来表达操作未指定键的属性,可能涉及type assertions,如上面的keyVal()

因此,虽然您可以表达TResponse,但这样做可能不值得。

无论如何,希望对您有所帮助;祝你好运!

Playground link to code

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-22
    • 1970-01-01
    • 2018-01-19
    • 2019-07-11
    • 2020-02-09
    • 2021-02-03
    相关资源
    最近更新 更多