【问题标题】:TypeScript: is there a way to do const assertions on the array return by Object.values?TypeScript:有没有办法对 Object.values 返回的数组进行 const 断言?
【发布时间】:2020-09-07 08:04:49
【问题描述】:

这是现场演示:https://codesandbox.io/s/vigorous-rgb-u860z?file=/src/index.ts

enum Keys {
  One = "one",
  Two = "two"
}

const a = Object.values(Keys).map((value, index) => ({
  label: value,
  id: String(index)
})) as const;

这是错误信息

“const”断言只能应用于对枚举的引用 成员,或字符串、数字、布尔值、数组或对象字面量。

我不确定我在这里缺少什么,因为Object.values 确实返回了一个数组。为什么我不能对它进行 const 断言

【问题讨论】:

  • 它应该读作/被读作:“.. array [literal], or object literal。”
  • 这里的“literal”限定符指的是字符串、数字、数组和对象。
  • 你可以做.map(... as const),这将导致一个隐含的const a:{ readonly label: Keys; readonly id: string; }[]

标签: javascript typescript


【解决方案1】:

您不能这样做的原因是因为 const 断言 X as const 的左侧 X 必须是 TypeScript 编译器知道的文字值。

所以我假设你的最终目标是你想要拥有完整类型的 A。没有任何特殊的东西你会得到这个:

const a: {
    label: Keys;
    id: string;
}[]

现在如果你想得到这个:

const a: [
    {
        label: "one";
        id: "0";
    },
    {
        label: "two";
        id: "1";
    }
]

这是不可能的,因为您依赖于Object.values 迭代顺序。这是由 ES2015 定义的,但 typescript 类型并不“知道”它。

通过一些简单的花哨类型,您可以得到:

type EnumEntry<T> = T extends any ? { label: T, id: string } : never;

const a: EnumEntry<Keys>[] = Object.values(Keys).map((value, index) => ({
  label: value,
  id: String(index)
}));
const a: ({
    label: Keys.One;
    id: string;
} | {
    label: Keys.Two;
    id: string;
})[]

但这是我认为我们可以做到的最好的事情,而不取决于 typescript 如何对类型进行排序。

【讨论】:

    【解决方案2】:

    这不完全是一个 const 断言,但您可以执行以下操作: as ReadonlyArray&lt;{label: Keys, id: string}&gt; 而不是 as const

    Playground link

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-21
      • 1970-01-01
      • 2012-09-23
      相关资源
      最近更新 更多