Здесь показаны различия между двумя версиями данной страницы.
| Предыдущая версия справа и слева Предыдущая версия | |||
|
typescript:types:interface [2023/01/29 20:48] werwolf |
typescript:types:interface [2023/01/29 20:50] (текущий) werwolf |
||
|---|---|---|---|
| Строка 35: | Строка 35: | ||
| В TypeScript интерфейс объявляется с помощью ключевого слова ''interface'', после которого указывается идентификатор (имя), за которым следует тело, заключенное в фигурные скобки, содержащее описание. | В TypeScript интерфейс объявляется с помощью ключевого слова ''interface'', после которого указывается идентификатор (имя), за которым следует тело, заключенное в фигурные скобки, содержащее описание. | ||
| - | <code> | + | <code javascript> |
| interface Identifier { | interface Identifier { | ||
| // тело интерфейса | // тело интерфейса | ||
| Строка 43: | Строка 43: | ||
| Объявление интерфейса возможно как в контексте модуля, так и в контексте функции или метода. | Объявление интерфейса возможно как в контексте модуля, так и в контексте функции или метода. | ||
| - | <code> | + | <code javascript> |
| interface Identifier {} // контекст модуля | interface Identifier {} // контекст модуля | ||
| Строка 63: | Строка 63: | ||
| Первый вид конвенций родом из языка Java — они предлагают именовать интерфейсы точно так же, как и классы. Допускаются имена прилагательные. | Первый вид конвенций родом из языка Java — они предлагают именовать интерфейсы точно так же, как и классы. Допускаются имена прилагательные. | ||
| - | <code> | + | <code javascript> |
| interface Identifier {} | interface Identifier {} | ||
| </code> | </code> | ||
| Строка 69: | Строка 69: | ||
| Второй вид предлагает использовать конвенции языка C#, по которым интерфейсы именуются так же, как классы, но с префиксом ''I'', что является сокращением от Interface. Такой вид записи получил название “венгерская нотация” в честь программиста венгерского происхождения, работавшего в компании MicroSoft. Допускаются имена прилагательные. | Второй вид предлагает использовать конвенции языка C#, по которым интерфейсы именуются так же, как классы, но с префиксом ''I'', что является сокращением от Interface. Такой вид записи получил название “венгерская нотация” в честь программиста венгерского происхождения, работавшего в компании MicroSoft. Допускаются имена прилагательные. | ||
| - | <code> | + | <code javascript> |
| interface IIdentifier {} | interface IIdentifier {} | ||
| </code> | </code> | ||
| Строка 81: | Строка 81: | ||
| Класс, реализующий интерфейс, обязан реализовывать его в полной мере. Любой класс, который хочет реализовать интерфейс, должен указать это с помощью ключевого слова ''implements'', после которого следует идентификатор реализуемого интерфейса. Указание реализации классом интерфейса располагается между идентификатором класса и его телом. | Класс, реализующий интерфейс, обязан реализовывать его в полной мере. Любой класс, который хочет реализовать интерфейс, должен указать это с помощью ключевого слова ''implements'', после которого следует идентификатор реализуемого интерфейса. Указание реализации классом интерфейса располагается между идентификатором класса и его телом. | ||
| - | <code> | + | <code javascript> |
| interface IAnimal { | interface IAnimal { | ||
| nickname: string; | nickname: string; | ||
| Строка 97: | Строка 97: | ||
| Один класс может реализовывать сколько угодно интерфейсов. В этом случае реализуемые интерфейсы должны быть перечислены через запятую. | Один класс может реализовывать сколько угодно интерфейсов. В этом случае реализуемые интерфейсы должны быть перечислены через запятую. | ||
| - | <code> | + | <code javascript> |
| interface IAnimal {} | interface IAnimal {} | ||
| interface IOviparous {} // указывает на возможность откладывать яйца | interface IOviparous {} // указывает на возможность откладывать яйца | ||
| Строка 106: | Строка 106: | ||
| В случае, когда класс расширяет другой класс, указание реализации (''implements'') следует после указания расширения (''extends''). | В случае, когда класс расширяет другой класс, указание реализации (''implements'') следует после указания расширения (''extends''). | ||
| - | <code> | + | <code javascript> |
| interface IAnimal {} | interface IAnimal {} | ||
| interface IOviparous {} | interface IOviparous {} | ||
| Строка 121: | Строка 121: | ||
| Несмотря на то, что в интерфейсе можно декларировать поля и методы, в нем нельзя декларировать свойства ''get'' и ''set'' (аксессоры). Но, несмотря на это, задекларированное в интерфейсе поле может быть совместимо не только с полем, но и аксессорами. При этом нет разницы, будет в объекте объявлен getter, setter или оба одновременно. | Несмотря на то, что в интерфейсе можно декларировать поля и методы, в нем нельзя декларировать свойства ''get'' и ''set'' (аксессоры). Но, несмотря на это, задекларированное в интерфейсе поле может быть совместимо не только с полем, но и аксессорами. При этом нет разницы, будет в объекте объявлен getter, setter или оба одновременно. | ||
| - | <code> | + | <code javascript> |
| interface IAnimal { | interface IAnimal { | ||
| id: string; | id: string; | ||
| Строка 152: | Строка 152: | ||
| Класс, реализующий интерфейс, принадлежит к типу этого интерфейса. Класс, унаследованный от класса, реализующего интерфейс, также наследует принадлежность к реализуемым им интерфейсам. В подобных сценариях говорят, что класс наследует интерфейс. | Класс, реализующий интерфейс, принадлежит к типу этого интерфейса. Класс, унаследованный от класса, реализующего интерфейс, также наследует принадлежность к реализуемым им интерфейсам. В подобных сценариях говорят, что класс наследует интерфейс. | ||
| - | <code> | + | <code javascript> |
| interface IAnimal {} | interface IAnimal {} | ||
| Строка 165: | Строка 165: | ||
| Класс, реализующий множество интерфейсов, принадлежит к типу каждого из них. Когда экземпляр класса, реализующего интерфейс, присваивают ссылке с типом интерфейса, то говорят, что экземпляр был ограничен типом интерфейса. То есть, функционал экземпляра класса урезается до описанного в интерфейсе (подробнее об этом речь пойдет в главе [[.|Совместимость объектов]]) и [[.|Совместимость функций]]). | Класс, реализующий множество интерфейсов, принадлежит к типу каждого из них. Когда экземпляр класса, реализующего интерфейс, присваивают ссылке с типом интерфейса, то говорят, что экземпляр был ограничен типом интерфейса. То есть, функционал экземпляра класса урезается до описанного в интерфейсе (подробнее об этом речь пойдет в главе [[.|Совместимость объектов]]) и [[.|Совместимость функций]]). | ||
| - | <code> | + | <code javascript> |
| interface IAnimal { | interface IAnimal { | ||
| name: string; | name: string; | ||
| Строка 196: | Строка 196: | ||
| Если множество логически связанных интерфейсов требуется объединить в один тип, то нужно воспользоваться механизмом расширения интерфейсов. Наследование интерфейсов осуществляется с помощью ключевого слова ''extends'', после которого через запятую идет один или несколько идентификаторов расширяемых интерфейсов. | Если множество логически связанных интерфейсов требуется объединить в один тип, то нужно воспользоваться механизмом расширения интерфейсов. Наследование интерфейсов осуществляется с помощью ключевого слова ''extends'', после которого через запятую идет один или несколько идентификаторов расширяемых интерфейсов. | ||
| - | <code> | + | <code javascript> |
| interface IIdentifiable {} | interface IIdentifiable {} | ||
| interface ILiving {} | interface ILiving {} | ||
| Строка 209: | Строка 209: | ||
| Для примера представьте приложение, которое только выводит в консоль информацию о животных. Так как над объектом ''Animal'' будет выполняться только одна операция, то можно не бояться разгневать богов объектно-ориентированного проектирования и включить все нужные характеристики прямо в интерфейс ''IAnimal''. | Для примера представьте приложение, которое только выводит в консоль информацию о животных. Так как над объектом ''Animal'' будет выполняться только одна операция, то можно не бояться разгневать богов объектно-ориентированного проектирования и включить все нужные характеристики прямо в интерфейс ''IAnimal''. | ||
| - | <code> | + | <code javascript> |
| interface IAnimal { | interface IAnimal { | ||
| id: string; | id: string; | ||
| Строка 244: | Строка 244: | ||
| Но если переписать программу, чтобы она выполняла несколько не связанных логически операций над одним типом, в данном случае ''IAnimal'', то ситуация изменится на противоположную. | Но если переписать программу, чтобы она выполняла несколько не связанных логически операций над одним типом, в данном случае ''IAnimal'', то ситуация изменится на противоположную. | ||
| - | <code> | + | <code javascript> |
| interface IAnimal { | interface IAnimal { | ||
| /*...*/ | /*...*/ | ||
| Строка 276: | Строка 276: | ||
| В этом случае программа нарушает принцип ISP, так как статические методы ''printId'' и ''printAge'' получили доступ к данным, которые им не требуются для успешного выполнения. Это может привести к намеренной или случайной порче данных. | В этом случае программа нарушает принцип ISP, так как статические методы ''printId'' и ''printAge'' получили доступ к данным, которые им не требуются для успешного выполнения. Это может привести к намеренной или случайной порче данных. | ||
| - | <code> | + | <code javascript> |
| class AnimalUtil { | class AnimalUtil { | ||
| public static printId(animal: IAnimal): void { | public static printId(animal: IAnimal): void { | ||
| Строка 294: | Строка 294: | ||
| Поэтому в подобных ситуациях настоятельно рекомендуется “дробить” типы интерфейсов на меньшие составляющие и затем ограничивать им доступ к данным. | Поэтому в подобных ситуациях настоятельно рекомендуется “дробить” типы интерфейсов на меньшие составляющие и затем ограничивать им доступ к данным. | ||
| - | <code> | + | <code javascript> |
| interface IIdentifiable {} | interface IIdentifiable {} | ||
| interface ILiving {} | interface ILiving {} | ||
| Строка 335: | Строка 335: | ||
| Когда интерфейс расширяет класс, он наследует описание членов, но не их реализацию. | Когда интерфейс расширяет класс, он наследует описание членов, но не их реализацию. | ||
| - | <code> | + | <code javascript> |
| class Animal { | class Animal { | ||
| nickname: string; | nickname: string; | ||
| Строка 355: | Строка 355: | ||
| Интерфейс, полученный путем расширения типа класса, может быть реализован только самим этим классом или его потомками, поскольку помимо публичных (''public'') также наследует закрытые (''private'') и защищенные (''protected'') члены. | Интерфейс, полученный путем расширения типа класса, может быть реализован только самим этим классом или его потомками, поскольку помимо публичных (''public'') также наследует закрытые (''private'') и защищенные (''protected'') члены. | ||
| - | <code> | + | <code javascript> |
| class Animal { | class Animal { | ||
| private uid: string; | private uid: string; | ||
| Строка 388: | Строка 388: | ||
| Конструктор указывается с помощью ключевого слова ''new'', затем открываются фигурные скобки, в которых при наличии указываются параметры, а в конце указывается тип возвращаемого значения. | Конструктор указывается с помощью ключевого слова ''new'', затем открываются фигурные скобки, в которых при наличии указываются параметры, а в конце указывается тип возвращаемого значения. | ||
| - | <code> | + | <code javascript> |
| new(p1: type, p2: type): type; | new(p1: type, p2: type): type; | ||
| </code> | </code> | ||
| Строка 394: | Строка 394: | ||
| Статические члены описываются так же, как и члены экземпляра. | Статические члены описываются так же, как и члены экземпляра. | ||
| - | <code> | + | <code javascript> |
| interface IAnimal { | interface IAnimal { | ||
| nickname: string; | nickname: string; | ||
| Строка 443: | Строка 443: | ||
| Помимо экземпляров и самих классов, интерфейсы могут описывать функциональные выражения. Это очень удобно, когда функциональный тип имеет большую сигнатуру, которая делает код менее читабельным. | Помимо экземпляров и самих классов, интерфейсы могут описывать функциональные выражения. Это очень удобно, когда функциональный тип имеет большую сигнатуру, которая делает код менее читабельным. | ||
| - | <code> | + | <code javascript> |
| // reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T; | // reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T; | ||
| var callback: ( | var callback: ( | ||
| Строка 455: | Строка 455: | ||
| В большинстве подобных случаев можно прибегнуть к помощи вывода типов. | В большинстве подобных случаев можно прибегнуть к помощи вывода типов. | ||
| - | <code> | + | <code javascript> |
| // reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T; | // reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T; | ||
| Строка 478: | Строка 478: | ||
| Но в случае, если функциональное выражение является параметром функции, как, например, метод массива ''reduce'', то решением может служить только явная декларация типа. | Но в случае, если функциональное выражение является параметром функции, как, например, метод массива ''reduce'', то решением может служить только явная декларация типа. | ||
| - | <code> | + | <code javascript> |
| class Collection<T> { | class Collection<T> { | ||
| reduce( | reduce( | ||
| Строка 498: | Строка 498: | ||
| Для этого необходимо в теле интерфейса описать сигнатуру функции без указания идентификатора. | Для этого необходимо в теле интерфейса описать сигнатуру функции без указания идентификатора. | ||
| - | <code> | + | <code javascript> |
| interface ISumAll { | interface ISumAll { | ||
| (...valueAll: number[]): number; | (...valueAll: number[]): number; | ||
| Строка 515: | Строка 515: | ||
| Индексные члены подробно будут рассматриваться в главе [[.|Объектные типы с индексными членами (объектный тип с динамическими ключами)]], но не будет лишним и здесь коснуться этого механизма. | Индексные члены подробно будут рассматриваться в главе [[.|Объектные типы с индексными членами (объектный тип с динамическими ключами)]], но не будет лишним и здесь коснуться этого механизма. | ||
| - | <code> | + | <code javascript> |
| interface IIndentifier { | interface IIndentifier { | ||
| [BindingIdentifier: string]: Type; | [BindingIdentifier: string]: Type; | ||
| Строка 528: | Строка 528: | ||
| Различие между ними заключается в том, что второй обладает только телом и объявляется прямо в аннотации типа. | Различие между ними заключается в том, что второй обладает только телом и объявляется прямо в аннотации типа. | ||
| - | <code> | + | <code javascript> |
| let identifier: { p1: type; p2: type }; | let identifier: { p1: type; p2: type }; | ||
| </code> | </code> | ||
| Строка 534: | Строка 534: | ||
| Интерфейс, объявленный с помощью ключевого слова ''interface'', считается идентичным инлайн интерфейсу, если их описание совпадает. Но стоит обратить внимание, что это возможно благодаря структурной типизации, которая рассматривается в главе [[.|Совместимость типов на основе вида типизации]]. | Интерфейс, объявленный с помощью ключевого слова ''interface'', считается идентичным инлайн интерфейсу, если их описание совпадает. Но стоит обратить внимание, что это возможно благодаря структурной типизации, которая рассматривается в главе [[.|Совместимость типов на основе вида типизации]]. | ||
| - | <code> | + | <code javascript> |
| interface IAnimal { | interface IAnimal { | ||
| nickname: string; | nickname: string; | ||
| Строка 552: | Строка 552: | ||
| Как было сказано ранее, инлайн интерфейс можно объявлять в тех местах, в которых допускается указание типа. Тем не менее реализовывать (''implements'') и расширять (''extends'') инлайн интерфейс нельзя. | Как было сказано ранее, инлайн интерфейс можно объявлять в тех местах, в которых допускается указание типа. Тем не менее реализовывать (''implements'') и расширять (''extends'') инлайн интерфейс нельзя. | ||
| - | <code> | + | <code javascript> |
| interface IT1 {} | interface IT1 {} | ||
| interface IT2 {} | interface IT2 {} | ||
| Строка 571: | Строка 571: | ||
| В случае, если в одной области видимости объявлено несколько одноимённых интерфейсов, то они будут объединены в один. | В случае, если в одной области видимости объявлено несколько одноимённых интерфейсов, то они будут объединены в один. | ||
| - | <code> | + | <code javascript> |
| // так видят разработчики | // так видят разработчики | ||
| interface IAnimal { | interface IAnimal { | ||
| Строка 597: | Строка 597: | ||
| При попытке переопределить тип поля возникнет ошибка. | При попытке переопределить тип поля возникнет ошибка. | ||
| - | <code> | + | <code javascript> |
| interface IAnimal { | interface IAnimal { | ||
| name: string; | name: string; | ||
| Строка 611: | Строка 611: | ||
| Если в нескольких одноимённых интерфейсах будут описаны одноимённые методы с разными сигнатурами, то они будут расценены, как описание перегрузки. К тому же, интерфейсы, которые описывают множество одноимённых методов, сохраняют свой внутренний порядок. | Если в нескольких одноимённых интерфейсах будут описаны одноимённые методы с разными сигнатурами, то они будут расценены, как описание перегрузки. К тому же, интерфейсы, которые описывают множество одноимённых методов, сохраняют свой внутренний порядок. | ||
| - | <code> | + | <code javascript> |
| interface IBird {} | interface IBird {} | ||
| interface IFish {} | interface IFish {} | ||
| Строка 648: | Строка 648: | ||
| Исключением из этого правила являются сигнатуры, которые имеют в своем описании литеральные строковые типы данных (''literal String Types''). Дело в том, что сигнатуры, содержащие в своем описании литеральные строковые типы, всегда размещаются перед сигнатурами, у которых нет в описании литеральных строковых типов. | Исключением из этого правила являются сигнатуры, которые имеют в своем описании литеральные строковые типы данных (''literal String Types''). Дело в том, что сигнатуры, содержащие в своем описании литеральные строковые типы, всегда размещаются перед сигнатурами, у которых нет в описании литеральных строковых типов. | ||
| - | <code> | + | <code javascript> |
| interface IBird {} | interface IBird {} | ||
| interface IFish {} | interface IFish {} | ||