打字稿:扩展接口并将现有字段重新声明为只读

时间:2016-12-17 17:28:53

标签: typescript readonly readonly-attribute

假设我们有这样的界面:

interface Person {
  name: string;
  age: number;
}

我想调用Readonly并创建一个只读版本的接口,例如

interface PersonReadonly extends Readonly<Person> {}

这相当于写作

interface PersonReadonly {
  readonly name: string;
  readonly age: number;
}

我们可以编写这样的Readonly通用接口,还是已经编写过?

4 个答案:

答案 0 :(得分:3)

回答你明确的问题:你在技术上不能做你想做的事。

类型映射将创建Type而非界面 - Readonly<T>是内置类型映射器,将返回Type。您无法实现或扩展Type别名,只能使用接口/类。

因此:

interface PersonReadonly extends Readonly<Person> {}
如果有support for implementing types are done

无效。

这并不能阻止你绕过Type;并且您可以在类型上使用union来构建更复杂的类型。因此你可以这样做:

type PersonWithState = Readonly<Person> & { state: string }

let person = <Person>{ name: "John", age: 20 };
let personState = <PersonWithState>{ ...person, state: "online" };

personState.age = "30"; // error;
personState.state = "offline"; // OK.

但是你不能拥有类实现或接口扩展PersonWithState

答案 1 :(得分:3)

你可以这样做:

type PersonReadonly = Readonly<Person>

但它不是一个界面。例如,您无法在其他位置添加新成员。

2017年5月编辑:自TS 2.2(2017年2月)起,interfaces can be derived from types

答案 2 :(得分:2)

在游乐场中,Readonly类型已定义,您可以执行以下操作:

interface Person {
    name: string;
    age: number;
}

let a: Readonly<Person> = {
    name: "name",
    age: 3
};

a.age = 5; // Error: Cannot assign to 'age' because it is a constant or a read-only property

code in playground

如果在您的环境中定义了类型,那么您只需添加它:

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

但它要求你有打字稿2.1及以上。
如果你没有它,可能意味着你的打字稿版本低于2.1,否则你可以使用它。

答案 3 :(得分:1)

TypeScript 2.1开始,用于创建实例readonly的所有字段的通用接口。

它的确称为Readonly<T>,因此您可以像这样使用它:

let person: Readonly<Person> = { name: 'John', age: 30 };
person.age = 31; // gives error

在TypeScript 2.1之前实现通用只读类型是不可能的。