В этом уроке мы поговорим об интерфейсах. Мы узнаем, что это такое, зачем они нужны, и в каких случаях их стоит использовать вместо типов.
Интерфейс — это конструкция языка TypeScript, которая используется, чтобы описывать объекты и функции.
Рассмотрим следующий пример:
interface IUser {
firstName: string;
pointsCount: number;
}
const user: IUser = {
firstName: 'Mark',
pointsCount: 100,
};
В данном фрагменте мы создали интерфейс и реализовали на его основе объект user
.
Интерфейс выглядит как определение объектного типа. Объектные типы и интерфейсы взаимозаменяемы почти во всех ситуациях. Сравним с примером выше:
type User = {
firstName: string;
pointsCount: number;
}
const user: User = {
firstName: 'Mark',
pointsCount: 100,
};
Здесь мы реализовали такой же объект, но уже на основе типа, а не интерфейса. Разницы почти нет.
Документация TypeScript говорит о том, что мы можем выбирать, что использовать — тип или интерфейс. Выбор зависит от ситуации. В таком случае возникает вопрос, зачем нужны интерфейсы, когда уже есть типы?
Интерфейсы и типы во многом похожи. Но есть отличия, на основе которых мы и можем выбирать, что именно следует использовать в конкретном случае.
Главная особенность интерфейсов связана с классами. Классы, которые реализуют интерфейсы, содержат внутри себя свойства и методы, указанные в реализуемом интерфейсе:
interface Countable {
count(): number;
}
class SchoolClass implements Countable {
// Тут какая-то логика
count(): number {
// Обязательно создать этот метод, так как он указан в интерфейсе
}
}
const sc = new SchoolClass();
// Возвращает число студентов в классе
sc.count();
В этом примере мы реализовали класс на основе интерфейса. Теперь во всех функциях, где объекты используются только для того, чтобы посчитать количество чего-либо внутри них, можно указывать Countable
вместо SchoolClass
:
// А не function doSomething(obj: SchoolClass)
function doSomething(obj: Countable) {
// Где-то внутри вызывается
obj.count();
}
Так благодаря интерфейсам функция становится более универсальной. Мы можем передать любые объекты, соответствующие Countable
, а не только SchoolClass
. В программировании такая возможность называется полиморфизмом подтипов (Subtyping).
Вам дан интерфейс IVehicle. Задача состоит в том, чтобы на основе этого интерфейса реализовать класс Car, который будет иметь метод calcFuelNeeded, принимающий расстояние в километрах и возвращающий расход топлива на указанную дистанцию. Также у класса Car должна быть функция-конструктор, которая принимает и реализует свойства, указанные в интерфейсе.
const porche = new Car(4, 'red', true, 20);
console.log(porche.calcFuelNeeded(200)); // 40
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Ваше упражнение проверяется по этим тестам
1import Car from './index';
2
3test('Car', () => {
4 const porche = new Car(4, 'red', true, 20);
5 expect(porche.calcFuelNeeded(100)).toBe(20);
6
7 const schoolBus = new Car(30, 'yellow', true, 24);
8 expect(schoolBus.calcFuelNeeded(25)).toBe(6);
9
10 const lada = new Car(4, 'white', true, 13);
11 expect(lada.calcFuelNeeded(200)).toBe(26);
12});
13
Решение учителя откроется через: