4

假设我们有一个这样的界面:

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

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

interface PersonReadonly extends Readonly<Person> {}

这相当于写作

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

我们可以编写这样一个 Readonly 泛型接口,还是已经编写好了?

4

4 回答 4

3

回答你明确的问题:从技术上讲,你还不能做你想做的事。

类型映射将创建一个Type非接口 -Readonly<T>是一个内置类型映射器,它将返回一个Type. 您不能实现或扩展Type别名,只能实现接口/类。

因此:

interface PersonReadonly extends Readonly<Person> {}

在对实现类型的支持完成之前是无效的,如果有的话。

不过,这并不能阻止您绕过 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- 还。

于 2016-12-17T17:44:31.843 回答
3

你可以做:

type PersonReadonly = Readonly<Person>

但它不是一个接口。例如,您不能在其他地方添加新成员。

从 2017 年 5 月开始编辑:从 TS 2.2(2017 年 2 月)开始,接口可以从 types 派生

于 2016-12-17T18:38:39.427 回答
2

在 PlaygroundReadonly中定义了类型,因此您可以执行以下操作:

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

操场上的代码

如果类型是在您的环境中定义的,那么您可以简单地添加它:

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

但它要求您拥有 typescript 2.1 及更高版本。
如果没有,可能说明你的 typescript 版本低于 2.1,否则你可以直接使用。

于 2016-12-17T17:35:32.630 回答
1

自TypeScript 2.1起,用于创建实例所有字段的通用接口readonly可用。

它被称为完全Readonly<T>,所以你可以像这样使用它:

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

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

于 2016-12-17T17:35:05.490 回答