我正在尝试在TS中创建只读接口,下面是我尝试过的readonly
修饰符传播到子类型的示例:
type JsonDatum =
| string
| boolean
| number
| readonly Json[]
| Object
| null
| undefined;
interface JsonInterface {
readonly [key: string]: Json;
}
type Json = JsonDatum | JsonInterface;
interface Player extends JsonInterface {
name: string;
countryCodes: number[];
elo: number;
}
const player: Player = {
name: "John Doe",
countryCodes: [1, 2, 3],
elo: 2000
}
player.name = "123" // No problem
player.countryCodes = [] // No problem
我认为,通过在JsonInterface
中添加readonly
修饰符,扩展它的接口也将具有其属性readonly
。但是没有问题。
为了使它发挥作用,我不得不采取这种非常非DRY的方法,并手动将readonly
s添加到子类型的所有属性中:
...
interface Player extends JsonInterface {
readonly name: string;
readonly countryCodes: number[];
readonly elo: number;
}
...
player.name = "123" // Cannot assign to 'name' because it is a read-only property.(2540)
player.countryCodes = [] // Cannot assign to 'name' because it is a read-only property.(2540)
这是TypeScript操场上的代码。
我想我会将我的方法转换为Readonly<T>
泛型,因为它似乎是更推荐的路径,但即使这样,似乎也存在问题。
(Readonly<T>
的定义似乎接近于我正在做的:type Readonly<T> = { readonly [P in keyof T]: T[P]; }
。我确实尝试用Readonly<T>
来调整上面的例子,但没有成功。(
这是预期的行为吗?是否有没有Readonly<T>
的变通方法?
这是预期的行为,正如您在这里看到的,Person
可以被认为是"覆盖";CCD_ 12中的定义。在这个修改后的例子中,效果更加明显。
这里很容易看出,即使JsonInterface
定义了readonly name
,Person
接口也会覆盖它
文档中有用的摘录:
接口上的
extends
关键字允许我们有效地复制其他命名类型的成员,并添加我们想要的任何新成员。这对于减少我们必须编写的类型声明样板文件的数量,以及发出同一属性的几个不同声明可能相关的意图非常有用。
真的没有容易的"变通办法";为此,但无论如何都应该使用Readonly<T>
(这就是它的用途!(。致";让它发挥作用";使用Readonly
,您可以尝试:
type Player = Readonly<{
name: string;
countryCodes: number[];
elo: number;
}>;
您可以在这里看到,结果是所需的类型。