【问题标题】:`as const` alternative to narrow an array literal tuple, to avoid `readonly` modifiers`as const` 替代缩小数组文字元组,以避免 `readonly` 修饰符
【发布时间】:2023-03-26 10:55:02
【问题描述】:

我们使用as const 来缩小类型:

[ {foo: 'foo' }, { bar: 'bar' } ] as const

但这也为所有道具和值添加了readonly 修饰符。从const 开始,这是有道理的,但我希望在没有readonly 修饰符的情况下进行缩小,因为您想修改元组中的对象,或者只是将其进一步传递给某些方法,这是相同的接口,但没有深readonly

let foo = [ {foo: 'foo' }, { bar: 'bar' } ]

这里的 foo 是类型:

({
    foo: string;
    bar?: undefined;
} | {
    bar: string;
    foo?: undefined;
})[]

但我希望得到

[{
    foo: string;
}, {
    bar: string;
}]

因为我们使用as const,但在大多数情况下这是不可能的,因为foo/bar 被深层嵌套readonly 修饰符,我们可以使用类似的东西

type DeepWritable<T> = { -readonly [P in keyof T]: DeepWritable<T[P]> };

但它会被连接到使用 as const 添加 readonly,然后使用 DeepWritable 删除它。

您是否知道as const 的任何替代方法来缩小元组类型而无需手动定义类型。

【问题讨论】:

  • 那么使用tuples 怎么样?您展示的这些数组的唯一共同点似乎不是它们的所有元素都是单一属性对象。这看起来确实像元组。
  • 那些元组是预定义的类型 - 你手动执行此操作,但我希望从文字声明中推断类型 - as const 正是这样做的,但另外添加了 readonly 修饰符,这使得它无用在大多数情况下,无需使用某些 Type Utils 进行进一步转换。
  • 这些answers - 特别是tuple 实用程序 - 适用于您的情况吗?我的意思是,类似于let foo = tuple({foo: 'foo' }, { bar: 'bar' })
  • 我实际上不喜欢这个选项的是函数本身:它那里,在编译的代码中,坐着什么也不做。我想这就是为什么相应的票 - github.com/microsoft/TypeScript/issues/16656 - 仍然活着并且在踢。
  • tuple 实用程序是有趣的解决方法,但正如您所提到的,编译代码中的存根方法不是很好。

标签: typescript typescript-typings


【解决方案1】:

您可以使用以下泛型函数将类型约束为元组:

const Tuple = <T extends [any, ...any]>(v:T) => v

然后包装文字:

let foo = Tuple([ {foo: 'foo' }, { bar: 'bar' } ]) // foo: [{ foo: string }, { bar: string }]

【讨论】:

  • 虽然我刚刚注意到您在 cmets 中讨论了类似的答案。无论如何,我将把它留在这里供您考虑。
  • 谢谢,对,但无论如何 - 这个解决方法也很有趣。
  • 酷,&lt;T extends [any, ...any]&gt; 似乎提供了很好的推理(有时我使用T extends ReadonlyArray&lt;any&gt;,但它更有限)。你知道任何关于它的文档吗?
猜你喜欢
  • 2021-09-15
  • 2015-11-10
  • 1970-01-01
  • 2019-05-28
  • 1970-01-01
  • 2019-04-08
  • 2019-05-16
  • 2013-05-12
  • 1970-01-01
相关资源
最近更新 更多