TypeScript - 移除 readonly 修饰符

79
在TypeScript中,是否有可能从类型中删除readonly修饰符?
例如:
type Writeable<T> = { [P in keyof T]: T[P] };

使用方法:

interface Foo {
    readonly bar: boolean;
}

let baz: Writeable<Foo>;

baz.bar = true;

是否有可能添加一个修饰符来使所有属性都可写?


1
有关该功能请求的官方TypeScript问题:https://github.com/microsoft/TypeScript/issues/24509 - Yves M.
1个回答

155
有一种方法:
type Writeable<T extends { [x: string]: any }, K extends string> = {
    [P in K]: T[P];
}

(在 playground 中查看代码)

但你也可以反其道而行之,这样会使事情变得更容易:

interface Foo {
    bar: boolean;
}

type ReadonlyFoo = Readonly<Foo>;

let baz: Foo;
baz.bar = true; // fine

(baz as ReadonlyFoo).bar = true; // error

(在代码播放区域查看)


更新

自 TypeScript 2.8 版本以来,有一种新的方式:

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

如果您需要递归地使类型可写,则:

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

这些type定义被称为映射类型


5
太棒了。我想知道为什么这不是标准类型?https://www.typescriptlang.org/docs/handbook/utility-types.html - Trade-Ideas Philip
1
type Writeable<T> = { -readonly [P in keyof T]: T[P] }; 即使在用作T的类中也可以很好地工作,因为当在TypeScript中使用class关键字时,实际上正在创建包含类的所有实例方法和属性的TypeScript interface!(知道第二个使用TypeScript class关键字创建的东西是具有不同(匿名)构造函数类型的JavaScript变量。) - RcoderNY
1
请注意,这个特定的实现在许多边缘情况下会失败 - 我发现来自 ts-essentialsDeepWritable 工具很好用,而且基本上是这个答案中呈现的工具的更完整版本(可以处理映射、函数、集合、承诺等)。 - Will S
1
FYI:type Writeable<T> = { -readonly [P in keyof T]: T[P] }; 对于只读元组类型(通常是从数组文字的const断言创建的)可以完美地工作,即使它看起来似乎只适用于对象。 - Geoff Davids
DeepWriteable真是救了我的一天,非常感谢! - xpol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接