【问题标题】:Use "as const" in Typescript without adding "readonly" modifiers?在 Typescript 中使用“as const”而不添加“readonly”修饰符?
【发布时间】:2021-09-15 20:56:43
【问题描述】:

如果我想定义一个元组或常量对象形状,我会使用as const。例如:

const arr = [{ a: 1 }] as const;

/* readonly [{
  readonly a: 1;
}] */

但是,我不想要readonly,因为我会得到很多The type 'readonly ...' is 'readonly' and cannot be assigned to the mutable type '...'

我定义了一个“可变”泛型:

type Mutable<T> = {
  -readonly [K in keyof T]: Mutable<T[K]>;
}

type Arr = Mutable<typeof arr>;

/* [Mutable<{
    readonly a: 1;
}>] */

但是,TS 不会在 VS Code 的类型预览中递归地应用 Mutable。换句话说,我希望 VS Code 的类型预览显示:

/* [{
    a: 1;
}] */

我认为 VS Code 不可能递归评估 Mutable,因为它可能太慢了。

有没有类似as const,但没有添加readonly

【问题讨论】:

  • 那么你想要什么?如果你正在寻找const arr: [{a: number}] = [{a: 1}];,那么就写吧。
  • 如果有类似 const 的东西,但没有添加 readonly,那么这就是我想要的
  • 所以你想得到[{a: 1}]的类型?
  • 是的,但语法与as const 一样简单。我认为这是不可能的

标签: javascript typescript visual-studio-code


【解决方案1】:

事实上,你已经让这个数组可变了。但是你可能已经注意到第一个元素的类型是{a: 1}

const arr = [{ a: 1 }] as const;

type Mutable<T> = {
    -readonly [K in keyof T]:  Mutable<T[K]>;
}

type Arr = Mutable<typeof arr>[0]; // {a: 1}

因为a 的字面量类型号为1,所以你仍然不能改变元素。

对不起,你可以,但你只能使用1

const x: Arr = [{ a: 1 }]
x[0].a = 1 // ok

为了使其完全可变,您应该将所有文字类型映射到更常见的类型。

1 -> number


type LiteralToCommon<T extends PropertyKey> =
    T extends number
    ? number : T extends string
    ? string : T extends symbol
    ? symbol : never;

type Mutable<T> = {
    -readonly [K in keyof T]: T[K] extends PropertyKey ? LiteralToCommon<T[K]> : Mutable<T[K]>;
}

const arr = [{ a: 1 }] as const;


type Arr = Mutable<typeof arr>;

const x: Arr = [{ a: 1 }]

x[0].a = 10 // ok

Playground

还有另一种方法:

type Mutable<T> = {
    -readonly [K in keyof T]: Mutable<T[K]>;
}

const arr = [{ a: 1 }];

type ImmutableArr = Readonly<typeof arr>

type MutableArr = Mutable<ImmutableArr>

type Arr = Mutable<typeof arr>;

const x: MutableArr = [{ a: 1 }]

x[0].a = 10 // ok

您可以只使用Readonly 作为数组。这个工具将{a: 1}推断为{a: number}

【讨论】:

    猜你喜欢
    • 2023-03-26
    • 1970-01-01
    • 2020-08-09
    • 2021-07-24
    • 1970-01-01
    • 2011-10-19
    • 2019-07-11
    • 2015-09-25
    • 2022-06-28
    相关资源
    最近更新 更多