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.