Typescript: расширение интерфейса и повторное выделение существующих полей только для чтения

Допустим, у нас есть такой интерфейс:

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

Я хочу вызвать Readonly и создать версию интерфейса только для чтения, например,

interface PersonReadonly extends Readonly<Person> {}

что будет эквивалентно написанию

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

Можем ли мы написать такой общий интерфейс Readonly, или он уже написан?

4 ответа

Решение

Ты можешь сделать:

type PersonReadonly = Readonly<Person>

Но это не интерфейс. Например, вы не можете добавить нового члена в другом месте.

Редактировать с мая 2017 года: Начиная с TS 2.2 (февраль 2017 года), интерфейсы могут быть получены из типов.

Чтобы ответить на прямой вопрос: технически вы пока не можете делать то, что хотите.

Тип Mapping создаст Type не интерфейс - Readonly<T> является встроенным типом отображения, который будет возвращать Type, Вы не можете реализовать или расширить Type псевдонимы, только интерфейс / класс.

таким образом:

interface PersonReadonly extends Readonly<Person> {}

недействителен, пока не будет реализована поддержка реализации типов, если вообще когда-либо.

Это не мешает вам проходить вокруг Типа; и вы можете использовать объединение типов, чтобы создавать более сложные типы. Таким образом, вы можете сделать:

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 - еще.

В детской площадке 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

( код на детской площадке)

Если тип определен в вашей среде, вы можете просто добавить его:

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

Но для этого требуется, чтобы у вас был машинописный текст 2.1 и выше.
Если у вас его нет, это, вероятно, означает, что ваша машинописная версия ниже 2.1, в противном случае вы можете просто использовать ее.

Общий интерфейс для создания всех полей экземпляра readonly доступно начиная с TypeScript 2.1.

Это называется точно Readonly<T> так что вы можете использовать это так:

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

Невозможно реализовать общий тип readonly до TypeScript 2.1.

Другие вопросы по тегам