简体   繁体   English

在 Typescript 中使用“as const”而不添加“readonly”修饰符?

[英]Use “as const” in Typescript without adding “readonly” modifiers?

If I want to define a tuple or constant object shape, I'd use as const .如果我想定义一个元组或常量对象形状,我会使用as const Eg:例如:

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

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

However, I don't want readonly because I'd get a lot of The type 'readonly ...' is 'readonly' and cannot be assigned to the mutable type '...'但是,我不想要readonly因为我会得到很多The type 'readonly ...' is 'readonly' and cannot be assigned to the mutable type '...'

I defined a "Mutable" generic:我定义了一个“可变”泛型:

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

type Arr = Mutable<typeof arr>;

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

However, TS doesn't recursively apply Mutable in VS Code's type preview.但是,TS 不会在 VS Code 的类型预览中递归应用Mutable In other words, I want VS Code's type preview to show:换句话说,我希望 VS Code 的类型预览显示:

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

I don't think it's possible for VS Code to recursively evaluate Mutable , since it could be too slow.我认为 VS Code 不可能递归评估Mutable ,因为它可能太慢了。

Is there something like as const , but without adding readonly ?是否有类似于as const东西,但没有添加readonly

In fact, you already made this array mutable.事实上,您已经使这个数组可变。 But you probably have noticed that type of first element is {a: 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}

Because a has literal type number 1 , you still can't mutate the element.因为a文字类型编号为1 ,所以您仍然无法改变元素。

Sorry, you can, but you are allowed to use only 1抱歉,您可以,但您只能使用1

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

In order to make it fully mutable, you should map all literal types to more commont types.为了使其完全可变,您应该将所有文字类型映射到更常见的类型。

1 -> number 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 操场

There is an alternative way:有一种替代方法:

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

You can use just Readonly for array.您可以仅将Readonly用于数组。 This util will infer {a: 1} as {a: number}此实用程序会将{a: 1}推断为{a: number}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM