- Objects & Object Type in TypeScript
- What is an object?
- Creating Objects in TypeScript
- Объектно-ориентированное программирование
- Поля класса
- Методы
- Конструкторы
- Поля для чтения
- Изучение TypeScript — полное руководство для начинающих. Часть 3 — Классы и интерфейсы
- Классы в TypeScript
- Модули в TypeScript
- Интерфейсы в TypeScript
- Интерфейсы с классами
Objects & Object Type in TypeScript
In this tutorial, let us look at the objects and learn how to create the object type and assign it to objects. objects are the most fundamental data type in TypeScript. The Typescript has seven primitive data types string , number , bigint , boolean , undefined , symbol , and null . Anything that is not a primitive data type is an object. Understanding objects and creating types to represent them is crucial in learning TypeScript. In this tutorial, we will learn what objects are in TypeScript and how to create types for objects and use them.
What is an object?
An object is a collection of key-value pairs. Each key-value pair is known as a property, where the key is the name of the property and value its value
Objects provide a way to group several values into a single value. You can group any values of other types like string, number, booleans, dates, arrays, etc. An object can also contain other objects. We can easily build a more complex structure using them.
Each key-value pair in the key-value collection is a property of the object. The TypeScript objects can have any number of properties. You can also create an empty object without any properties. The key or name of the property must be unique. The property name is string (But can also be a symbol type). No two properties can have the same name. We store or retrieve the value of an object using its property name (key). Value can be any valid TypeScript value. For example string, number, date, function, or another object.
We can also assign a function to a property in which case the property is known as a method.
Creating Objects in TypeScript
There are a few ways in which you can create an object in TypeScript. One of the is to use the Object Literal Syntax. It consists of a list of key-value pairs, each separated by a comma and wrapped inside curly braces
Объектно-ориентированное программирование
TypeScript реализует объектно-ориентированный подход, в нем есть полноценная поддержка классов. Класс представляет шаблон для создания объектов и инкапсулирует функциональность, которую должен иметь объект. Класс определяет состояние и поведение, которыми обладает объект.
Для определения нового класса применяется ключевое слово class . Например, определим класс User:
После определения класса мы можем создавать его объекты:
let tom: User = new User(); let alice = new User();
Здесь определено два объекта класса User — tom и alice.
Поля класса
Для хранения состояния объекта в классе определяются поля:
Здесь определены два поля — name и age , которые имеют типы string и number соответственно. Фактически поля представляют переменные уровня класса, только для их объявления не применяются var и let .
По имени объекта мы можем обращаться к этим полям:
class User < name: string; age: number; >let tom = new User(); tom.name = "Tom"; tom.age = 36; console.log(`name: $ age: $`); // name: Tom age: 36
При определении полей им можно задать некоторые начальные значения:
class User < name: string = "Tom Smith"; age: number = 18; >let user = new User(); console.log(`name: $ age: $`); // name: Tom Smith age: 18
Методы
Классы также могут определять поведение — некоторые действия, которые должны выполнять объекты этого класса. Для этого внутри класса определяются функции, которые называются методами.
class User < name: string; age: number; print()< console.log(`name: $age: $`); > toString(): string< return `$: $`; > >
Здесь в классе User определены два метода. Метод print() выводит информацию об объекте на консоль, а метод toString() возвращает некоторое представление объекта в виде строки.
В отличие от обычных функций для определения методов не указывается ключевое слово function .
Для обращения внутри методов к полям и другим методам класса применяется ключевое слово this , которое указывает на текущий объект этого класса.
class User < name: string; age: number; print()< console.log(`name: $age: $`); > toString(): string< return `$: $`; > > let tom = new User(); tom.name = "Tom"; tom.age = 36; tom.print(); // name: Tom age: 36 console.log(tom.toString()); // Tom: 36
Конструкторы
Кроме обычных методов классы имеют специальные функции — конструкторы, которые определяются с помощью ключевого слова constructor . Конструкторы выполняют начальную инициализацию объекта. Например, добавим в класс User конструктор:
class User < name: string; age: number; constructor(userName: string, userAge: number) < this.name = userName; this.age = userAge; >print() < console.log(`name: $age: $`); > > let tom = new User("Tom", 36); tom.print(); // name: Tom age: 36
Здесь конструктор применимает два параметра и использует их значения для установки значения полей name и age:
constructor(userName: string, userAge: number)
Затем при создании объекта в конструктор передается два значения для его параметров:
Поля для чтения
Полям класса в процессе работы программы можно присваивать различные значения, которые соответствуют типу полей. Однако TypeScript также позволяет определять поля для чтения, значения которых нельзя изменить (кроме как в конструкторе). Для определения таких полей применяется ключевое слово readonly :
Значение полей для чтения можно установить либо при объявлении:
readonly name: string = "Default user";
constructor(userName: string, userAge: number)
В остальных местах программы значение этого поля нельзя изменить. Например, в следующем случае мы получим при компиляции ошибку, потому что пытаемся установить поле для чтения:
class User < readonly name: string = "Default user"; age: number; constructor(userName: string, userAge: number) < this.name = userName; this.age = userAge; >print() < console.log(`name: $age: $`); > > let tom = new User("Tom", 36); tom.name = "Bob"; // ! Ошибка - поле name - только для чтения tom.print(); // name: Tom age: 36
Изучение TypeScript — полное руководство для начинающих. Часть 3 — Классы и интерфейсы
Всем привет! Меня зовут Лихопой Кирилл, я работаю fullstack-разработчиком. Это — уже третья часть руководства по TypeScript для начинающих, в которой мы разберем более сложные темы, такие как классы, модули и интерфейсы.
Классы в TypeScript
Мы можем определить типы для любых данных, которые будут в классе:
class Person < name: string; isCool: boolean; friends: number; constructor(n: string, c: boolean, f: number) < this.name = n; this.isCool = c; this.friends = f; >sayHello() < return `Привет, меня зовут $, у меня есть $ друзей` > > const person1 = new Person('Денис', false, 10); const person2 = new Person('Вова', 'да', 6); // ОШИБКА: Аргумент типа 'string' не может быть присвоен параметру с типом 'boolean' console.log(person1.sayHello()); // Привет, меня зовут Денис, у меня есть 10 друзей
Затем мы можем создать массив people , в котором содержаться экземпляры класса Person :
let People: Person[] = [person1, person2];
Мы можем добавить модификаторы доступа к свойствам класса. TypeScript также предоставляет новый модификатора доступа readonly (мы говорили о нем в прошлой части):
class Person < readonly name: string; // это свойство неизменно - его можно только прочитать private isCool: boolean; // можно прочитать и изменять только в пределах этого класса protected email: string; // можно прочитать и изменить только из класса и наследуемых от него public friends: number; // можно прочитать и изменить откуда угодно, даже вне класса constructor(n: string, c: boolean, e: string, f: number) < this.name = n; this.isCool = c; this.email = e; this.friends = f; >sayMyName() < console.log(`Ты не Хайзенберг, ты $`); > > const person1 = new Person('Менделеев', false, 'men@de.ru', 118); console.log(person.name); // все в порядке person1.name = 'Хайзенберг'; // ОШИБКА: только для чтения console.log(person1.isCool); // ОШИБКА: private свойство - доступ есть только в пределах класса Person console.log(person1.email); // ОШИБКА: protected свойство - доступ есть только в пределах класса Person и его наследниках console.log(person1.friends); // public свойство - никаких проблем
Мы можем сделать наш код более лаконичным, если опишем свойства класса следующим образом:
class Person < constructor( readonly name: string, private isCool: boolean, protected email: string, public friends: number )<>sayMyName() < console.log(`Ты не Хайзенберг, ты $`); > > const person1 = new Person('Менделеев', false, 'men@de.ru', 118); console.log(person.name); // Менделеев
Когда мы описываем класс таким образом, свойства назначаются автоматически прямо в конструкторе, спасая нас от их повторного написания.
Обратите внимание — когда мы пропускаем модификатор доступа, то по умолчанию свойство будет public .
Классы могут наследоваться, так же, как и в обычном JavaScript:
class Programmer extends Person < programmingLanguages: string[]; constructor( name: string, isCool: boolean, email: string, friends: number, pL: string[] )< // Вызов super должен содержать все параметры базового класса (Person), т.к. конструктор не наследуется super(name, isCool, email, friends); this.programmingLanguages = pl; >>
Больше о классах вы можете узнать на официальном сайте TypeScript.
Модули в TypeScript
В JavaScript модули — это просто файлы, которые содержат связанный код. Функционал может быть импортирован и экспортирован между модулями, чтобы сохранять код в организованном виде.
TypeScript так же имеет поддержку модулей. Файлы TypeScript будут компилироваться в отдельные JavaScript файлы.
Измените следующие параметры в файле tsconfig.json , чтобы добавить поддержку современных экспорта и импорта:
"target": "es2016", "module": "es2015"
(Несмотря на то, что для Node-проекта вам, вероятно, очень хочется добавить «module»:»CommonJS» , это не сработает, т.к. Node еще не поддерживает современные экспорт и импорт.)
Теперь, добавьте атрибут type=»module» в тег скрипта в вашем HTML-файле:
Теперь мы можем импортировать и экспортировать файлы с помощью ES6:
// src/hello.ts export function sayHi() < console.log('Всем привет!'); >// src/script.ts import < sayHi >from './hello.js'; syaHi(); // Всем привет!
Обратите внимание: всегда импортируйте файл с разрешением .js , даже если это TypeScript-файл.
Интерфейсы в TypeScript
Интерфейсы объявляются как объекты и выглядят следующим образом:
interface Person < name: string; age: number; >function sayHi(person: Person) < console.log(Привет, $); > sayHi(< name: 'Джон', age: 33, >); // Привет, Джон
Вы также можете объявлять их как объекты, используя type (псевдоним типа):
type Person = < name: string; age: number; >function sayHi(person: Person) < console.log(Привет, $); > sayHi(< name: 'Джон', age: 33, >); // Привет, Джон
А еще тип объекта может быть указан анонимно, прямо в параметрах функции:
function sayHi(person: < name: string; age: number >) < console.log(`Привет, $`); > sayHi(< name: 'Джон', age: 33, >); // Привет, Джон
Интерфейсы очень похожи на псевдонимы типов, и во многих случаях вы можете использовать их обоих. Их ключевое различие — псевдонимы нельзя наследовать, а интерфейсы можно.
interface Animal < name: string >interface Bear extends Animal < honey: boolean >const bear: Bear =
Изучение TypeScript — полное руководство для начинающих. Часть 3 — Классы и интерфейсы. типов:
type Animal = < name: string >type Bear = Animal & < honey: boolean >const bear: Bear =
Добавление новых полей к существующему интерфейсу:
interface Animal < name: string >// Добавление поля к интерфейсу interface Animal < tail: boolean >const dog: Animal =
А вот и разница: типы не могут изменены после объявления:
type Animal = < name: string >type Animal = < tail: boolean >// ОШИБКА: Дублирующийся идентификатор 'Animal'.
Документация TypeScript советует использовать интерфейсы для объявления объектов, если вам не требуется использовать возможности типов.
Также в интерфейсе можно указать типы данных для параметров функции и значения, которое она возвращает:
interface Person < name: string age: number speak(sentence: string): void >const person1: Person = < name: 'Джон', age: 33, speak: sentence =>console.log(sentence), >
У вас мог возникнуть вопрос: почему мы используем интерфейсы вместо классов в примере выше?
Во-первых, интерфейсы используются только в TypeScript, не в JavaScript. Это значит, что они не будут скомпилированы, и соответственно не будут раздувать наш JavaScript-файл. А так как классы используются в JavaScript, то они будут скомпилированы.
Во-вторых, класс это, по сути своей, фабрика объектов (то есть это “план” того, как должен выглядеть объект), в то время как интерфейсы используются исключительно для проверки типов.
Класс может инициализировать свойства и методы, чтобы помочь создавать объекты, а интерфейсы просто описывают, какие свойства должен иметь объект и каких типов они будут.
Интерфейсы с классами
Мы можем указать классу, что он должен содержать определенные свойства и методы путем реализации интерфейса:
interface HasFormatter < format(): string; >class Person implements HasFormatter < constructor(public username: string, protected password: string) <>format() < return this.username.toLocaleLowerCase(); >> // Должно быть объектом, который реализует интерфейс HasFormatter let person1: HasFormatter; let person2: HasFormatter; person1 = new Person('Денис', 'password123'); person2 = new Person('Женя', 'TypeScripter999'); console.log(person1.format()); // Денис
На этом третья часть цикла подходит к концу, жду вас в следующей статье, в которой будут рассмотрены такие понятия, как литералы, дженерики и еще несколько тем.
P.S. Автор искренне извиняется за большой перерыв между второй и третью частями, который связан с огромными переменами в жизни (в т.ч. релокейт в Казахстан)