Ты неправильно используешь интерфейсы typescript
A: Не думай о помощи.
Б: Сложно не думать о помощи, когда пишешь на javascript.
Примерно такой диалог я слышал на одной из конференции. Решить проблему отсутствия строгой типизации был призван typescript.
Конкретно в этой статье я хотел бы рассмотреть один из приемов использования интерфейсов typescript, который мне кажется неочевидным, его я подсмотрел и смог оценить его преимущества в процессе написания приложений на языке golang.
Для большинства typescript разработчиков типы и интерфейсы, не имеют как таковой большой разницы.
type Dog = {name: string, age: number}
interface Dog {
name: string,
age: number
}
И запись при помощи интерфейса и при помощи типа по своей сути равнозначно смогут дальше работать, и подсказывать ошибки типизации при дальнейшей разработке
Что я предлагаю?
Я предлагаю разделять эти 2 понятия:
Типы используем когда хотим описать определенные атрибуты объектов.
Интерфейсы когда хотим описать поведение объектов, их методы.
Для начала создадим интерфейс «greeter».
interface greeter {
greet() : void;
}
Создадим типы «Dog» и «Cat».
type Dog = {name: string, age: number}
type Cat = {first_name: string, second_name: string, owner: string}
Как мы видим эти типы, имеют различные наборы атрибутов.
Далее создадим функцию, которая принимает в качестве первого аргумента, объект удовлетворяющий интерфейсу «greeter» и далее вызывает его метод «greet».
function greet(g: greeter) {
g.greet();
}
Что-бы наши типы «Dog» и «Cat», можно было использовать при вызове функции «greet», необходимо явно объединить типы «Dog» и «Cat» c интерфейсом «greeter»
type Dog = {name: string, age: number} & greeter
type Cat = {first_name: string, second_name: string, owner: string} & greeter
Реализуем объект каждого типа
const dog: Dog = {
name: "jack",
age: 10,
greet() {
console.log(`hello im dog. My name is ${this.name}. I'm ${this.age} years old.`)
}
}
const cat: Cat = {
first_name: "Myley",
second_name: "Meows",
owner: "Ivan",
greet() {
console.log(`hello im cat. My name is ${this.first_name} ${this.second_name}. My owner name is ${this.owner}`);
}
}
Что мы имеем? У нас 2 объекта, разные по своей реализации, но их объединяет наличие метода, указанного в интерфейсе «greeter»
Вызовем эти методы
greet(dog);//"hello im dog. My name is jack. I'm 10 years old."
greet(cat);//"hello im cat. My name is Myley Meows. My owner name is Ivan"
Итог:
Интерфейсы позволяют разделять реализацию от так называемого слоя бизнеса.
Например с точки зрения реализации пользователя и администратора в рамках одного приложения, они могут иметь различный набор атрибутов. Но в конце концов для их создания, нужно использовать один и тот же хендлер бекенда.
Код становится чище и в результате более легким для восприятия.
Позволяет разделять приложения, на более мелкие, независимые слои.