Содержание
Интерфейсы | JavaScript Camp
Одним из основных принципов TypeScript является то, что типизация основана на структуре объектов. Такой способ типизации называют неявной
или «утиной»
— объект относят к тому или иному типу (классу, интерфейсу), если он имеет (реализует) все его свойства и методы. Интерфейсы в TS применяются как раз для того, чтобы описывать нужные вам типы.
Простой пример
Лучший способ узнать, как работают интерфейсы — начасть с простого примера:
Пример
let giveFruit = (fruit: { name: string }) => console.log('Give to me ' + fruit.name)let myFruits = { name: 'Banana', sweetness: 7, bones: false }
giveFruit(myFruits)
Функция giveFruit()
имеет единственный параметр, который требует, чтобы переданный объект имел свойство с именем name
типа string
. Обратите внимание, что наш объект на самом деле имеет больше свойств, чем требуется, но компилятор только проверяет, присутствуют ли хотя бы те, которые необходимы, и соответствуют требуемым типам.
Напишем тот же пример, для проверки свойства name
с типом string
, но при помощи интерфейсов.
Пример
interface Fruit {
name: string
sweetness: number
bones: boolean
}let giveFruit = (fruit: Fruit) => console.log('Give to me ' + fruit.name)
let myFruits = { name: 'Banana', sweetness: 7, bones: false }
giveFruit(myFruits)
Интерфейс Fruit
— это имя, которое мы теперь можем использовать для описания требования в предыдущем примере. Обратите внимание, что нам не нужно было явно указывать, что объект, который мы передаем в функцию giveFruit()
, наследует этот интерфейс, как это может быть в других языках. Здесь важен только образец. Если объект, который мы передаем функции, соответствует перечисленным требованиям, то всё позволено.
Стоит отметить, что проверка типов не требует, чтобы эти свойства имели какой-либо порядок, а только то, что свойства, необходимые для интерфейса, присутствуют и имеют требуемый тип.
Необязательные свойства
Не все свойства интерфейса могут быть обязательными. Некоторые существуют при определенных условиях или могут вообще отсутствовать. Интерфейсы с необязательными свойствами записываются аналогично другим интерфейсам, где каждое необязательное свойство обозначается знаком ?
в конце имени свойства в декларации.
Пример
interface Fruit {
name: string
sweetness: number
bones: boolean
color?: number
}let banana: Fruit = {
name: 'Banana',
sweetness: 7,
bones: false,
color: 0xffe135
}let apple: Fruit = {
name: 'Apple',
sweetness: 5,
bones: true
}
Необязательные свойства популярны при создании шаблонов, таких как «option bags», в которых вы передаете объект в функцию, у которого заполнены только пара свойств.
Только для чтения
Некоторые свойства могут быть заданы только для чтения, а значение они получат при создании объекта. Этого можно добиться, поместив ключевое слово readonly перед именем свойства.
Пример
interface Point {
readonly x: number;
readonly y: number;
}let a1: Point = { x: 10, y: 40 }
console.log('Точка [' + a1.x + '; ' + a1.y + ']')
Можно создать переменную c типом Point
, присвоив ей литерал объекта. После этого значения свойств x
и y
изменять будет нельзя.
Лишние свойства
В нашем первом примере использования интерфейсов TypeScript позволил передать { name: string; sweetness: number, bones: boolean }
там, где ожидалось всего лишь { name: string }
. Также мы узнали о необязательных свойствах, и о том, как они могут быть полезны при передаче аргументов в функции. Рассмотрим пример.
Пример
interface Fruit {
name: string
sweetness?: number
bones?: boolean
color?: number
}function addFruit(x: Fruit): { name: string; color: number } {
// . ..
}let banana = addFruit({ name: 'banana', colour: 0xffe135 })
// error: 'colour' not expected in type 'Fruit'
Обратите внимание, что аргумент, передаваемый в addFruit()
, записан как colour
вместо color
. В чистом JavaScript подобные вещи не выдают ошибок, но и не работают так, как хотел бы разработчик.
Можно сказать, что данная программа корректна с точки зрения типов, так как типы свойств sweetness
совместимы, color
отсутствует, а наличие дополнительного свойства colour
не имеет никакого значения.
Однако TypeScript делает предположение, что в этом куске кода есть ошибка. Литералы объектов обрабатываются им по-особенному, и проходят проверку на наличие лишних свойств. Эта проверка делается, когда литералы либо присваиваются другим переменным, либо передаются в качестве аргументов. Если в литерале есть какие-либо свойства, которых нет в целевом типе, то это будет считаться ошибкой.
Обойти такую ошибку можно несколькими способами.
Первый способ
Использование приведение типов:
Пример
let banana = addFruit({ name: 'banana', colour: 0xFFE135 } as Fruit)
Второй способ
Добавление строкового индекса, его лучше использовать тогда, когда вы уверены, что объект может иметь дополнительные свойства.
Пример
interface Fruit {
name: string
color?: number
[propName: string]: any
}
В данном примере интерфейс Fruit
может иметь любое количество свойств. Если это не name
или color
, то тип свойства не имеет значения.
Третий способ
Присвоить объект другой переменной. Из-за присваивания объекта другой переменной он не будет проходить проверку на избыточные свойства, компилятор не выдаст ошибки.
Пример
let options = { name: 'banana', colour: 0xffe135 },
banana = addFruit(options)
Стоит иметь ввиду, что для простого кода не стоит обходить данные проверки свойств. Для более сложных литералов объектов, которые содержат в себе методы, параметры состояния и т.д., стоит держать в памяти данные способы обхода проверок, но все же большинство ошибок, связанных с проверкой лишних свойств, как правило, на самом деле являются ошибками. Если у вас возникает такая ошибка, возможно стоит пересмотреть объявление типа.
Типы функций
Помимо описания свойств, интерфейсы также позволяют описывать типы функций.
Для описания типа функции в интерфейсе, в нем нужно определить сигнатуру вызова. Это похоже на объявление функции только со списком параметров и типом возвращаемого значения. Каждый параметр в списке должен иметь имя и тип.
interface SearchFunc {
(source: string, subString: string): boolean
}
Определив такой интерфейс один раз, мы можем его использовать также как и все другие интерфейсы. Пример ниже показывает, как определить переменную с типом функции и присвоить ей значение.
Пример
interface SearchFunc {
(source: string, subString: string): boolean
}let mySearch: SearchFunc
mySearch = function (source: string, subString: string) {
let result = source. search(subString)
if (result == -1) {
return false
} else {
return true
}
}console.log(mySearch('banana lime apple', 'banana'))
Имена параметров не обязательно должны совпадать, чтобы функция прошла проверку на соответствие типов. Мы, к примеру, могли бы записать предыдущий пример — вот так:
Пример
interface SearchFunc {
(source: string, subString: string): boolean
}let mySearch: SearchFunc
mySearch = (src: string, sub: string): boolean => {
let result = src.search(sub)
if (result == -1) {
return false
} else {
return true
}
}console.log(mySearch('banana lime apple', 'banana'))
Параметры функций проверяются друг за другом, и типы параметров, находящихся на соответствующих позициях, сравниваются попарно. Если вы не хотите указывать типы для аргументов, то TypeScript сможет вывести типы из контекста, основываясь на том, что функция присваивается переменной, тип которой — SearchFunc. В следующем примере тип возвращаемого значения функции тоже выводится: это делается на основании значений, которые она возвращает false
и true
. Если бы функция возвращала числа или строки, то компилятор во время проверки типов предупредил бы, что тип возвращаемого значения не совпадает с типом, указанным в интерфейсе SearchFunc.
Пример
interface SearchFunc {
(source: string, subString: string): boolean;
}let mySearch: SearchFunc
mySearch = (src, sub) => {
let result = src.search(sub)
if (result == -1) {
return false
} else {
return true
}
}console.log(mySearch('banana lime apple', 'banana'))
Индексируемые типы
Аналогично тому, как мы можем использовать интерфейсы для описания типов функций, мы также можем описывать типы, в которые мы можем «индексировать», например, a[10]
или ageMap["daniel"]
. Индексируемые типы имеют сигнатуру индекса, которая описывает типы, которые мы можем использовать для индексации объекта, вместе с соответствующими типами возврата при индексации.
Пример
interface StringArray {
[index: number]: string
}let myArray: StringArray
myArray = ['Bob', 'Fred']let myStr: string = myArray[0]
console.log(myArray[0])
Здесь у нас есть интерфейс StringArray
, у которого есть сигнатура индекса. Эта сигнатура говорит о том, что, когда StringArray
индексируется числом, возвращается строка.
Расширение интерфейсов
Интерфейсы могут расширять друг друга. Это позволяет вам копировать элементы одного интерфейса в другой, что дает вам больше гибкости в том, как вы разделяете свои интерфейсы на повторно используемые компоненты.
Пример
interface Shape {
color: string
}interface PenStroke {
penWidth: number
}// множественное расширение
interface Square extends Shape, PenStroke {
sideLength: number
}let square = {} as Square
square.color = 'blue'
square.sideLength = 10
square. penWidth = 5.0
Гибридные типы
Как мы упоминали ранее, интерфейсы могут описывать более сложные типы, присутствующие в реальном мире JavaScript. Из-за динамического и гибкого характера JavaScript вы можете случайно встретить объект, который работает как комбинация некоторых типов, описанных выше.
Одним из таких примеров является объект, который действует как функция и объект с дополнительными свойствами:
Пример
interface Counter {
(start: number): string
interval: number
reset(): void
}function getCounter(): Counter {
let counter = function (start: number) {} as Counter
counter.interval = 123
counter.reset = function () {}
return counter
}let c = getCounter()
c(10)
c.reset()
c.interval = 5.0
Вопросы
Как называется способ типизации, используемый в TypeScript?
- явный
- утиный
- строгий
С помощью какого ключевого слова объявляется интерфейс?
- interface
- class
- function
С помощью какого символа объявляется необязательное свойство?
!
?
-
Для чего используется readonly
?
- Только для чтения
- Только для записи
- Незнаю
Позволяют ли интерфейсы описывать типы функций?
true
false
С помощью какого ключевого слова расширяются интерфейсы?
- yield
- extends
- export
Теперь мы готовы с вами изучать TypeScript, но для того чтобы понять на сколько вы усвоили этот урок пройдите тест в мобильном приложении в нашей школы по этой теме.
Ссылки
- TypeScriptLang
- Интерфейсы
Contributors ✨
Thanks goes to these wonderful people (emoji key):
IIo3iTiv 📖 | Dmitriy Vasilev 💵 |
Интерфейс (interface) — что это такое простыми словами: виды
Интерфейс — это набор инструментов, который позволяет пользователю взаимодействовать с программой. В более широком смысле термин обозначает любые инструменты для соприкосновения между разными системами и сущностями. Часто говорят о графическом интерфейсе — это внешний вид сайта, программы или приложения.
Слово буквально означает «место соприкосновения», поэтому в IT интерфейсом могут называть разные сущности, с первого взгляда не похожие друг на друга. Например, в объектно-ориентированном программировании интерфейс — это набор методов сущности, то есть набор действий, с помощью которых она может взаимодействовать с другими. В веб-разработке интерфейс — внешний вид сайта. А для консольной программы интерфейс — набор команд, которые можно вводить в консоль, чтобы управлять поведением этой программы.
Все эти значения объединяет одно: то, что называется интерфейсом, служит для связи между одним и другим.
Интерфейсами пользуются абсолютно все, кто использует компьютеры, смартфоны или другие гаджеты. Интерфейс есть практически у любой программы, с которой вы работаете: браузера, графического редактора, мессенджера и чего угодно другого. С программой без интерфейса нельзя взаимодействовать. Это службы операционной системы, системные процессы, которые работают «в фоне» без участия пользователя.
В более узком смысле с интерфейсами работают UI-дизайнеры или разработчики, если речь идет не о графическом интерфейсе. Разработчики же реализуют интерфейс так, чтобы он был функциональным и понятным.
Курс
Уверенный старт в IT
Поможем определить подходящую вам IT-профессию и освоить её с нуля. Вы на практике попробуете разные направления: разработку на разных языках, аналитику данных, Data Science, менеджмент в IT. Это самый подходящий курс для построения карьеры в IT в новой реальности. Скидка на курс до 60% в честь Черной пятницы и продвинутый карьерный модуль в подарок.
Подробнее
Графический интерфейс, Graphic User Unterface — то, о чем мы говорили выше. Вы открываете любую программу, и на экране появляется окно. Все, что в этом окне, — текст, кнопки, слайдеры, картинки — интерфейс программы. То же самое с сайтами и приложениями. Внешний вид открывшегося сайта — его графический интерфейс. Окно с приложением — интерфейс.
Это аббревиатура для интерфейса командной строки, Command Line Interface. Он текстовый, не графический. Все, что происходит, описывается текстом; команды пользователь набирает в отдельной строке, самой нижней. Этот интерфейс выглядит просто как множество строк текста на однотонном фоне. Иногда текст разных цветов: цвета обозначают разные виды информации.
Когда-то графических интерфейсов не существовало, и люди работали за компьютером через CLI. И сейчас есть программы или даже целые операционные системы без GUI. Все взаимодействие с ними происходит через командную строку.
«Базовый» CLI системы включает в себя набор команд, которые нужны для управления ОС. Когда вы скачиваете какой-то инструмент или программу, чаще всего профессиональные, вы иногда можете установить вместе с ней ее CLI, чтобы более гибко управлять процессами.
Интерфейсом командной строки пользуются в основном специалисты: разработчики, системные администраторы, сетевые инженеры и другие.
Application Programming Interface — отдельный вид интерфейса. Им пользуются не люди, а программы, поэтому он и называется программным. Например, если владелец сайта добавляет на страницы возможность комментирования через соцсети — он пользуется API соцсети, чтобы его сайт мог с ней связаться.
С некоторыми устройствами можно взаимодействовать с помощью голоса и жестов. Пример — умный дом, который включает свет по определенному жесту, или колонка с голосовым помощником. Голос и жесты в таком случае — способ взаимодействия, то есть интерфейс.
Общение между двумя людьми — тоже пример голосового и жестового интерфейсов.
Узнать, как продумывать и разрабатывать хорошие, функциональные интерфейсы, вы можете на наших профессиональных курсах.
Курс
Frontend- разработчик PRO
Получите перспективную творческую профессию и знания уровня middle. Вы изучите JavaScript и TypeScript. За время обучения вы выполните 5 проектов на JavaScript и получите 13 проектов в портфолио. Скидка на курс до 60% в честь Черной пятницы и продвинутый карьерный модуль в подарок.
Подробнее
javascript — «Интерфейс» в документации MDN для JS?
Я много раз сталкивался со словом « интерфейс », когда читал документацию MDN для JS, но так и не понял, к чему оно относится.
Я знаю, что в JS нет такого понятия, как «интерфейс», как в Java, C#, TypeScript и всех других подобных языках ООП.
Насколько мне известно, интерфейс — это просто набор определений свойств и методов (не реализаций), которые должен реализовать определенный класс, чтобы соответствовать определенному интерфейсу, но это, опять же, не относится к JS.
Теперь давайте представим, что MDN говорит о некотором свойстве некоторого объекта, скажем, geolocation
свойство window.navigator
возвращает объект GeolocationPosition/GeolocationPositionError
. Затем мы читаем, что эти объекты соответствуют интерфейсу(ам) GeolocationPosition/GeolocationPositionError
.
Проверка интерфейсов GeolocationPosition/GeolocationPositionError
через console.dir
возвращает, что они являются функциями. Значит ли это, что GeolocationPosition/GeolocationPositionError
Объекты, возвращенные при доступе к свойству geolocation
в window. navigator
, являются просто объектами, созданными функциями GeolocationPosition/GeolocationPositionError
?
Итак, относится ли термин интерфейс
в документации MDN просто к функции, которая создает объекты с определенными свойствами и методами, как обычные функции-конструкторы?
Тогда почему я не могу создать новый GeolocationPosition/GeolocationPositionError
объектов, использующих эти функции GeolocationPosition/GeolocationPositionError
и новый оператор
?
- javascript
- браузер
- интерфейс
3
Интерфейс на самом деле имеет четко определенное значение в контексте веб-API браузера.
Интерфейс в этом контексте является интерфейсом WebIDL. WebIDL — это «язык спецификации интерфейса», на основе которого строятся такие вещи, как HTML и спецификации DOM.
Например, window. navigator
реализует интерфейс навигатора:
[Exposed=Window] навигатор интерфейса { // объекты, реализующие этот интерфейс, также реализуют интерфейсы, указанные ниже }; Навигатор включает в себя NavigatorID; Navigator включает NavigatorLanguage; Navigator включает NavigatorOnLine; Navigator включает NavigatorContentUtils; Navigator включает NavigatorCookies; Navigator включает плагины NavigatorPlugins; Navigator включает NavigatorConcurrentHardware;
Интерфейсы аналогичны тому, что вы ожидаете от «OO-языков»:
Фрагменты
IDL используются для описания объектно-ориентированных систем. В таких системах объекты — это объекты, обладающие идентичностью и являющиеся инкапсуляцией состояния и поведения. Интерфейс — это определение (соответствующее интерфейсу InterfaceRest), которое объявляет некоторое состояние и поведение, которые будет предоставлять объект, реализующий этот интерфейс.
Интерфейс — это спецификация набора членов интерфейса (соответствующих InterfaceMembers). Это члены, которые появляются между фигурными скобками в объявлении интерфейса.
Интерфейсы в Web IDL описывают, как ведут себя объекты, реализующие интерфейс. В привязках для объектно-ориентированных языков ожидается, что объект, реализующий конкретный интерфейс IDL, предоставляет способы проверки и изменения состояния объекта и вызова поведения, описанного интерфейсом.
Интерфейс может быть определен для наследования от другого интерфейса. Если за идентификатором интерфейса следует символ U+003A COLON («:») и идентификатор, то этот идентификатор идентифицирует унаследованный интерфейс. Объект, реализующий интерфейс, наследуемый от другого, также реализует этот унаследованный интерфейс. Таким образом, объект также будет иметь элементы, соответствующие элементам интерфейса из унаследованного интерфейса.
Все из спецификации WebIDL.
Что касается того, почему вы не можете создавать свои собственные экземпляры реализаций, которые браузер предоставляет для этих интерфейсов?
Я подозреваю, что GeolocationPositionError
, например, не может быть создан, потому что он не отображается в окне
. Если это полезно для пользователей, вы можете открыть запрос функции в репозитории whatwg/html.
0
В документах MDN слово 9Интерфейс 0098 часто используется, чтобы говорить об API (интерфейс прикладного программирования). Действительно, единственное, о чем вам как разработчику нужно беспокоиться, — это API (а не детали реализации, лежащие в основе API).
Интерфейсы являются концептуальными только в JavaScript, но они существуют в некоторых расширяющих языках, таких как TypeScript.
4
Зарегистрируйтесь или войдите в систему
Зарегистрируйтесь с помощью Google
Зарегистрироваться через Facebook
Зарегистрируйтесь, используя электронную почту и пароль
Опубликовать как гость
Электронная почта
Обязательно, но не отображается
Опубликовать как гость
Электронная почта
Требуется, но не отображается
javascript — Разница между интерфейсом и абстрактным классом (JS)
спросил
Изменено
4 месяца назад
Просмотрено
9к раз
Ограничение абстрактного класса заключается в том, что подкласс может расширять только один абстрактный класс. Следовательно, в интерфейсах встречается множественное наследование.
Интерфейсы могут иметь конкретные методы точно так же, как абстрактные классы, но не могут иметь поля экземпляра, только общедоступные, статические, конечные поля.
Правильно ли я понимаю, что единственная разница заключается в том, что интерфейсы просто не могут иметь поля экземпляра?
- javascript
- интерфейс
- абстрактный класс
5
интерфейс
часто является своего рода объявлением типа, тогда как класс
или абстрактный класс
— это объявление класса
, которые в JS являются просто конструкторами, хотя они часто определяют определенный «тип» значений. abstract
являются особым случаем между ними, потому что они определяют новое конкретное значение (конструктор в JS), но не могут быть созданы без подкласса.
Итог, интерфейсов
— это объявление в пространстве типов, тогда как [абстрактный] класс
— это объявление в пространстве значений. Например, в машинописном тексте вы можете соединить их, используя 9Класс 0011 реализует . В JavaScript термин интерфейс чаще относится к общей форме поведения определенного типа значения, возвращаемого некоторым API (см. https://developer.mozilla.org/en-US/docs/Web/API/Event, где термин Интерфейс
используется для описания различного рода событий).
Интерфейсы описывают только то, какие свойства и методы должны быть реализованы, и не описывают, как методы должны работать.
Но абстрактные классы могут описывать, как работает метод, как в обычных классах. Например:
абстрактный класс MyClass { abstract method_1() // метод без реализации method_2() { // метод с реализацией // сделай что-нибудь } }
Интерфейсы выглядят так:
интерфейс MyInterface { метод_1(): недействителен; метод_2(): строка; }
3
Я предполагаю, что ваш вопрос относится к Typescript, потому что объявления «interface» и «abstract» могут использоваться только в Typescript.