Открыть список
Как стать автором
Обновить

Книга «TypeScript быстро»

Блог компании Издательский дом «Питер»Профессиональная литератураTypeScript
image Привет, Хаброжители! «TypeScript быстро» научит вас секретам продуктивной разработки веб- или самостоятельных приложений. Она написана практиками для практиков. В книге разбираются актуальные для каждого программиста задачи, объясняется синтаксис языка и описывается разработка нескольких приложений, в том числе нетривиальных — так вы сможете понять, как использовать TypeScript с популярными библиотеками и фреймворками. Вы разберетесь с превосходным инструментарием TypeScript и узнаете, как объединить в одном проекте TypeScript и JavaScript. Среди продвинутых тем, рассмотренных авторами, – декораторы, асинхронная обработка и динамические импорты. Прочитав эту книгу, вы поймете, что именно делает TypeScript особенным.

Для кого эта книга
Эта книга написана для инженеров ПО, которые хотят повысить продуктивность разработки веб- или самостоятельных приложений. Мы, ее авторы, являемся практиками и книгу писали для таких же практиков. В ней не только объясняется синтаксис языка на простых примерах, но также описывается разработка нескольких приложений — так вы можете понять, как использовать TypeScript с популярными библиотеками и фреймворками.

В процессе создания этой книги мы проводили мастер-классы, используя приведенные в ней образцы кода. Это позволило получить раннюю обратную связь по содержанию книги. Надеемся, что вы получите удовольствие от процесса изучения TypeScript.

Этот материал, в свою очередь, предполагает, что у читателей уже есть практические познания в HTML, CSS и JavaScript, использующем последние нововведения из спецификации ECMAScript. Если вам знаком только синтаксис ECMAScript 5, рекомендуем просмотреть приложение, чтобы лучше понимать примеры кода, используемые в книге. Приложение выполняет роль введения в современный JavaScript.

Структура книги
Эта книга состоит из двух частей. В части 1 мы рассматриваем различные элементы синтаксиса TypeScript, приводя для наглядности небольшие образцы кода. В части 2 мы используем TypeScript в нескольких версиях блокчейн-приложения. Если ваша цель — как можно быстрее освоить синтаксис TypeScript и сопутствующие инструменты, тогда части 1 будет достаточно.

Глава 1 поможет начать разработку с помощью TypeScript. Вы скомпилируете и запустите самые простые программы, чтобы понять суть рабочего процесса — от написания программ в TypeScript и до их компиляции в выполняемый JavaScript. Мы также рассмотрим преимущества программирования в TypeScript в сравнении с JavaScript и представим вам редактор Visual Studio Code.

Глава 2 поясняет, как объявлять переменные и функции с типами. Вы научитесь объявлять псевдонимы типов с помощью ключевого слова type, а также узнаете, как объявлять пользовательские типы с классами и интерфейсами. Это поможет понять разницу между номинальными и структурными системами типов.

Глава 3 рассказывает, как работает наследование классов и когда использовать абстрактные классы. Вы увидите, как с помощью интерфейсов в TypeScript можно принудить класс иметь методы с известными сигнатурами, не беспокоясь при этом о деталях реализации. Вы также узнаете, что означает «программирование через интерфейсы».

Глава 4 посвящена перечислениям и обобщенным типам. Она рассматривает преимущества использования перечислений, синтаксис для численных и строчных перечислений, назначение обобщенных типов, а также показывает, как прописывать классы, интерфейсы и поддерживающие их функции.

Глава 5 описывает декораторы, а также отображенные и условные типы. Все это относится к продвинутым типам TypeScript, поэтому для понимания этой главы следует ознакомиться с синтаксисом обобщенных типов.

Глава 6 посвящена сопутствующим инструментам. В ней мы рассказываем об использовании карт кода и TSLinter (несмотря на то, что TSLinter считается устаревшим, многие разработчики по-прежнему им пользуются). Затем мы покажем вам, как компилировать и обвязывать (bundle) приложения TypeScript с помощью Webpack. Вы также узнаете, как и зачем компилировать TypeScript с помощью Babel.

Глава 7 научит вас использовать библиотеки JavaScript в вашем TypeScript-приложении. Мы начнем с объяснения роли файлов определений типов, а затем представим небольшое приложение, использующее библиотеку JavaScript в приложении TypeScript. В завершение мы пройдем через весь процесс постепенного перевода имеющегося проекта JavaScript в TypeScript.

В части 2 мы используем TypeScript в блокчейн-приложении. Здесь вы можете подумать: «Ни одна из компаний, где я работал, не использует блокчейн, так зачем мне его изучать, если моя цель — освоение TypeScript?» Мы не хотели, чтобы наш образец приложения был очередным стандартным примером, поэтому озадачились поиском горячей технологии, в которой можно было бы применить различные элементы TypeScript, а также техники, представленные в части 1. Знакомство с тем, как TypeScript может быть использован в нетривиальном приложении, придаст содержанию больше практичности, даже если вы не собираетесь использовать блокчейн в ближайшем будущем.

В этой части книги вы разработаете несколько блокчейн-приложений: самостоятельное приложение, браузерное приложение, а также приложения на Angular, React.js и Vue.js. При этом можете выбрать к прочтению только интересующие вас главы, но обязательно прочитайте главы 8 и 10, где объясняются основные принципы.

Глава 8 представляет принципы блокчейн-приложений. В ней вы узнаете, для чего нужно хеширование функций, что означает блокчейн-майнинг и почему для добавления нового блока в блокчейн требуется подтверждение работы. После знакомства с основами блокчейна мы представим проект и поясним код, лежащий в основе простого блокчейн-приложения. Большинство глав в части 2 имеют рабочие проекты с подробным пояснением того, как они были написаны и как запускаются.

В главе 9 описывается создание веб-клиента для блокчейна. Это приложение не будет использовать никакие фреймворки; в нем мы задействуем только HTML, CSS и TypeScript. Мы также создадим небольшую библиотеку для генерации хеша, которую можно будет использовать как в веб-, так и в самостоятельных клиентах. Помимо этого, вы увидите, как производить отладку кода TypeScript в своем браузере.

Глава 10 рассматривает код блокчейн-приложения, использующего сервер обмена сообщениями для связи между членами блокчейна. Мы создадим Node.js и WebSocket сервер в TypeScript и покажем вам, как для достижения консенсуса блокчейн использует правило длиннейшей цепочки. Вы найдете практические примеры использования TypeScript интерфейсов, абстрактных классов, квалификаторов доступа, перечислений и обобщенных типов.

В главе 11 дается краткий обзор разработки веб-приложений в Angular при помощи TypeScript, а глава 12 рассматривает код блокчейн-веб-клиента, разработанного с помощью этого фреймворка.

Глава 13 дает краткое введение в разработку веб-приложений в React.js с помощью TypeScript, а глава 14 рассматривает код блокчейн-веб-клиента, разработанного с React.

Глава 15 аналогичным образом представляет разработку веб-приложений в Vue.js с помощью TypeScript, а глава 16 рассматривает блокчейн-веб-клиент, разработанный с использованием Vue.

Использование компилятора BABEL


Babel — это популярный JS-компилятор, предлагающий решение для широко известной проблемы: не все браузеры поддерживают весь набор возможностей, объявленных в ECMAScript. Мы даже не говорим о полной реализации конкретной версии ECMAScript. В любой момент времени один из браузеров может реализовать конкретную выборку возможностей из ECMAScript 2019, в то время как другой по-прежнему будет понимать только ECMAScript 5. Посетите сайт caniuse.com и поищите arrow functions (стрелочные функции). Вы увидите, что Internet Explorer 11, OperaMini и некоторые другие браузеры их не поддерживают.

Если вы разрабатываете новое веб-приложение, то захотите протестировать его для всех браузеров, которые могут использоваться вашей целевой аудиторией. Babel позволяет вам писать современный JS и компилировать его в более старые версии. Несмотря на то что tsc дает возможность указать для компиляции конкретную целевую спецификацию ECMAScript (например, ES2019), Babel более точен. Он позволяет выборочно указать возможности языка, которые требуется трансформировать в JavaScript, поддерживаемый старыми браузерами.

На рис. 6.9 показан фрагмент таблицы совместимости с браузерами (из mng.bz/O9qw). Сверху вы видите названия браузеров и компиляторов, а слева расположен список возможностей. Браузер, компилятор или среда выполнения сервера могут полностью либо частично поддерживать некоторые из перечисленных возможностей, а плагины Babel позволяют указывать только конкретные из них, которые требуется трансформировать в более старый код. Полный список плагинов можно посмотреть в документации Babel: babeljs.io/docs/en/plugins.

image

В целях этого рассмотрения мы выбрали функцию «Обрезка строк» из ES2019 (см. черную стрелку слева от рис. 6.9). Давайте предположим, что наше приложение должно работать в браузере Edge. Проследуйте по вертикальной стрелке, и вы увидите, что Edge 18 на данный момент реализует обрезку строк только частично (2/4).

Мы можем использовать функцию обрезки строк в нашем коде, но нужно попросить Babel скомпилировать эту возможность в более старый синтаксис. Когда Edge все-таки начнет поддерживать эту функцию полноценно и компиляции не потребуется, гибкости Babel окажется достаточно.

Babel состоит из множества плагинов, каждый из которых компилирует конкретную функцию языка, но попытка найти и отобразить функции в плагины может потребовать много времени. Именно поэтому плагины Babel скомбинированы в предустановки, являющиеся списками именно тех из них, которые вы хотите применить для компиляции. В частности, preset-env позволяет указывать возможности ECMAScript и браузеры, которые должно поддерживать ваше приложение.

В разделе A.12 приложения мы включили скриншот из babeljs.io, иллюстрирующий Babel-инструмент REPL. Взгляните на меню Babel Try it now, показанное на рис. 6.10, где вы увидите навигационную панель, позволяющую конфигурировать предустановки.

Каждая предустановка просто является группой плагинов, и если вы хотите скомпилировать код в синтаксис ES2015, достаточно отметить галочкой es2015. Вместо указания имен спецификаций ECMAScript вы можете настраивать конкретные версии браузеров или других сред выполнения, используя опцию ENV PRESET. Белая стрелка на рис. 6.10 показывает редактируемое окошко с предполагаемыми значениями для предустановки ENV: >2%, ie11, safari>9. Это означает, что вы хотите, чтобы Babel скомпилировал код для запуска во всех браузерах, имеющих рыночный охват не менее 2%, а также в Internet Explorer 11 и Safari.

Ни IE11, ни Safari 9 не поддерживают стрелочные функции, и если вы введете (a, b) ?a+b;, Babel преобразует это в JS, который перечисленные браузеры понимают, как показано в правой части рис. 6.11.

СОВЕТ Если вы видите ошибки после ввода имен браузеров, уберите галочку Enabled после введения браузеров и версий. Это похоже на баг, но к моменту прочтения вами этой книги он может быть уже устранен.

Теперь давайте изменим предустановку на «last 2 chrome versions» (две последние версии Chrome), как показано на рис. 6.12. Babel достаточно сообразителен, чтобы понять, что последние две версии Chrome поддерживают стрелочные функции и нет нужды производить преобразование.

image

Предустановка ENV идет со списком браузеров, и вам нужно использовать верные имена и фразы, чтобы указать ограничения (например, last2majorversions, Firefox>=20 или >5% in US). Эти фразы перечислены в проекте browserslist, который доступен здесь.

Мы использовали предустановку ENV в Babel REPL, чтобы поиграть с целевыми средами, но эти настройки могут быть также сконфигурированы и использованы из командной строки. В листинге 6.15 мы добавим в файл конфигурации .babelrc следующее: babel/preset-env. В листинге 6.17 вы увидите файл .browserlistrc, в котором вы можете настроить конкретные браузеры и версии, как мы делали в Babel REPL. Подробнее о preset-env вы можете прочитать в документации Babel здесь: babeljs.io/docs/en/next/babel-preset-env.html.

image

Babel может использоваться для компиляции таких языков, как JavaScript, TypeScript, CoffeeScript, Flow и др. Например, фреймворк React использует синтаксис JSX, который не относится к стандарту JS, и Babel это понимает. В главе 12 мы используем Babel с приложением React.

Когда Babel компилирует TS, он не выполняет проверку типов в отличие от tsc. Создатели Babel не реализовали полноценный компилятор TS. Babel просто считывает TS-код и генерирует соответствующий синтаксис JS.

Должно быть, вы подумали: «Я вполне доволен компилятором TS. Зачем вообще в эту книгу о TypeScript включать раздел о компиляторе JS-в-JS?» Причина в том, что вы можете подключиться к проекту, где часть модулей написаны в JS, а часть в TS. В таких проектах Babel может уже быть частью потока разработки-развертывания. Например, Babel популярен среди разработчиков, использующих фреймворк React, который лишь недавно начал поддерживать TS.

Подобно любому npm-пакету, вы можете установить Babel локально или глобально (с опцией -g). Локальная установка внутри директории проекта делает этот проект самодостаточным, так как после запуска npm install вы можете использовать Babel, не ожидая, что он установлен где-то в другом месте (кто-нибудь может работать над вашим проектом с другого компьютера).

npm install babel/core babel/cli babel/preset-env

Здесь babel/core является компилятором Babel, babel/cli — интерфейсом командной строки, а babel/preset-env — это предустановка ENV, которую мы недавно рассматривали.

В реестре npmjs.org пакеты JavaScript могут быть организованы как ветки. Например, babel — это ветка для пакетов, относящихся к Babel. angular — это ветка для пакетов, принадлежащих фреймворку Angular. @types — это место для файлов определений типов TS для различных популярных JS-библиотек.

В последующих разделах мы представим вам три небольших проекта. Первый использует Babel с JS, второй — Babel с TS, а третий — Babel, TS и Webpack.

Использование Babel с JavaScript

В этом разделе мы рассмотрим простой проект, использующий Babel с JavaScript и расположенный в директории babel-javascript. Мы продолжим работать с трехстрочным скриптом index.js, представленным в листинге 6.7 и использующем JS-библиотеку Chalk. Единственное изменение в следующем листинге заключается в том, что сообщение теперь гласит «Compiled with Babel» (Скомпилировано с помощью Babel).

Листинг 6.15. index.js: исходный код приложения babel-javascript

const chalk = require('chalk');
const message = 'Compiled with Babel';
console.log(chalk.black.bgGreenBright(message));

Следующий листинг показывает npm-скрипт, который мы будем использовать для запуска Babel и зависимостей, которые должны быть установлены на машине разработчика.

image

Babel настраивается в файле .babelrc, и наш файл конфигурации будет очень прост. Нам нужно только использовать preset-env для компиляции.

Листинг 6.17. Файл .babelrc

{
    "presets": [
       "@babel/preset-env"
    ]
}

Мы не настраивали здесь никакие конкретные версии браузеров, и без каких бы то ни было опций конфигурации babel/preset-env ведет себя в точности так же, как babel/preset-es2015, babel/preset-es2016 и babel/preset-es2017. Другими словами, все возможности языка, представленные в ECMAScript2015, 2016 и 2017, будут скомпилированы в ES5.

СОВЕТ Мы сконфигурировали Babel в файле .babelrc, который отлично подходит для статических конфигураций вроде нашей. Если ваш проект требует программного создания конфигураций Babel, вам понадобится использовать файл babel.config.js (подробнее в документации Babel здесь: babeljs.io/docs/en/config-files#project- wide-configuration). Если вы хотите увидеть, как Babel компилирует наш файл src/index.js, установите зависимости этого проекта, выполнив npm install, а затем запустите npm-скрипт из package.json: npm run babel.

Следующий листинг показывает скомпилированную версию index.js, созданную в директории dist. Она будет иметь следующее содержимое (сравните с листингом 6.15):

image

Скомпилированный файл по-прежнему вызывает require('chalk'), и эта библиотека расположена в отдельном файле. Помните, что Babel — это не бандлер. Мы используем Webpack с Babel в разделе 6.4.3.

Можете запустить скомпилированную версию так:

node dist/index.js

Вывод консоли будет выглядеть схожим с изображенным на рис. 6.13.

Если бы мы захотели, чтобы Babel генерировал код, работающий в конкретных версиях браузеров, потребовалось бы добавить дополнительный файл конфигурации, .browserslistrc. Например, нам нужно, чтобы код работал только в двух последних версиях Chrome и Firefox. Мы можем создать следующий файл в корне проекта:

image

Листинг 6.19. Пример файла .browserslistrc

last 2 chrome versions
last 2 firefox versions

Теперь при запуске Babel не будет преобразовывать const в var, как в листинге 6.18, потому что и Firefox, и Chrome уже поддерживают ключевое слово const. Попробуйте сами, чтобы убедиться.

Использование Babel с TypeScript

В этом разделе мы рассмотрим простой проект, использующий Babel с TypeScript; он размещен в директории babel-typescript. Мы продолжим работать с трехстрочным скриптом, представленным в листинге 6.11 и использующим JS-библиотеку Chalk. Единственное изменение будет в том, что теперь сообщение гласит «Compiled with Babel» (Скомпилировано с помощью Babel).

Листинг 6.20. index.ts: исходный код приложения babel-typescript

import chalk from 'chalk';
const message: string = 'Compiled with Babel';
console.log(chalk.black.bgGreenBright(message));

В сравнении с package.json из чистого JS-проекта (см. листинг 6.16) наш TS-проект добавляет dev-зависимость preset-typescript, отделяющую типы TS от кода, чтобы Babel мог воспринимать его как чистый JS. Мы также добавим опцию --extensions '.ts' в npm-скрипт, запускающий Babel, как в листинге 6.21. Теперь Babel будет считывать файлы .ts.

image

Как правило, предустановки включают набор плагинов, но preset-typescript содержит только один, babel/plugin-transform-typescript. Этот плагин внутренне использует babel/plugin-syntax-typescript, чтобы считывать TypeScript, и babel/helper-plugin-utils для основных утилит плагинов.

Несмотря на то что babel/plugin-transform-typescript преобразует TS-код в синтаксис ES.Next, это не компилятор TS. Как бы странно это ни звучало, Babel просто стирает TypeScript. Например, он преобразует const x: number = 0 в const x = 0. babel/plugin-transform-typescript намного быстрее, чем компилятор TS, так как не производит проверку типов для вводных файлов.

babel/plugin-transform-typescript имеет несколько небольших ограничений, перечисленных в документации на babeljs.io/docs/en/babel-plugin-transform-typescript (например, он не поддерживает const enum). Для лучшей поддержки TS рассмотрите использование плагинов babel/plugin-proposal-class-properties и babel/plugin-proposal-object-rest-spread.

Прочитав первые пять глав этой книги, вы наверняка уже начали ценить проверку типов и обнаружение ошибок во время компиляции, осуществляемое реальным компилятором TS. Неужели теперь мы действительно предлагаем вам использовать Babel, чтобы стереть связанный с TS синтаксис? Не совсем так. В процессе разработки вы можете продолжать использовать tsc (с помощью tsconfig.json) и IDE с полной поддержкой TypeScript. Тем не менее на стадии развертывания вы можете все же ввести Babel- и ENV-предустановки. (Скорее всего, вы уже оценили гибкость, предлагаемую ENV-предустановками, при конфигурировании целевых браузеров, не так ли?)

В вашем процессе сборки вы можете даже добавить npm-скрипт (в package.json), запускающий tsc:

«check_types»: «tsc --noEmit src/index.ts»

Теперь вы можете последовательно запустить check_types и Babel при наличии локально установленного tsc:

npm run check_types && npm run babel

Опция --noEmit гарантирует, что tsc не сгенерирует никаких файлов (вроде index.js), так как это будет сделано командой babel, выполняемой сразу после check_types. Если в index.js присутствуют ошибки компиляции, процесс сборки провалится и команда babel даже не запустится.

СОВЕТ Если вы используете && (двойной амперсанд) между двумя npm-скриптами, они будут выполняться последовательно. Для параллельного выполнения используйте & (одинарный амперсанд). Подробности вы можете найти во врезке «Использование амперсандов в npm-скриптах в Windows» в главе 10.

В этом проекте файл конфигурации .babelrc включает babel/preset-typescript.

Листинг 6.22. Файл .babelrc

{
"presets": [
"@babel/preset-env",
"@babel/preset-typescript"
]
}

В сравнении с проектом babel-javascript мы сделали следующие относящиеся к TypeScript изменения:

  • Добавили опцию --extensions '.ts' в команду, запускающую Babel.
  • Добавили в package.json связанные с TypeScript dev-зависимости.
  • Добавили babel/preset-typescript в файл конфигурации .babelrc.

Чтобы скомпилировать наш простой скрипт index.ts, запустите следующий npm-скрипт из package.json:

npm run babel

Вы найдете скомпилированную версию index.js в директории dist. Вы можете запустить скомпилированный код так же, как мы это делали в предыдущем разделе:

node dist/index.js

Теперь давайте добавим в наш рабочий поток Webpack, чтобы связать скрипт index.js и JS библиотеку Chalk.

Использование Babel с TypeScript и Webpack

Babel — это компилятор, но не бандлер, который необходим для любого реального приложения. Вы вольны выбирать из ряда доступных бандлеров (вроде Webpack, Rollup и Browserify), но мы будем придерживаться Webpack. В этом разделе мы рассмотрим простой проект, использующий Babel с TypeScript и Webpack. Расположен он в директории webpack-babel-typescript.

В разделе 6.3.2 мы рассмотрели настройку TypeScript-Webpack, и далее мы продолжим использовать наш трехстрочный исходный код из того проекта.

Листинг 6.23. index.ts: исходный код приложения webpack-babel-typescript

import chalk from 'chalk';
const message: string = 'Built with Babel bundled with Webpack';
console.log(chalk.black.bgGreenBright(message));

В следующем листинге показан раздел devDependency из package.json.

image

Сравните зависимости Babel в листингах 6.24 и 6.21. В листинге 6.24 присутствуют три изменения:

  • Мы добавили babel-loader, являющийся Webpack-загрузчиком для Babel.
  • Мы удалили babel-cli, потому что не будем запускать Babel из командной строки.
  • Вместо babel-cli Webpack будет использовать babel-loader как часть процесса связывания.

Как вы помните из раздела 6.3, Webpack использует файл конфигурации webpack.config.js. Для настройки TS с помощью Webpack мы использовали ts-loader (см. листинг 6.14). В данном же случае мы хотим, чтобы файлы с расширением .ts обрабатывал babel-loader. Следующий листинг показывает раздел Babel из файла webpack.config.js.

image

Файл .babelrc будет выглядеть в точности так же, как и в предыдущем разделе (см. листинг 6.20).

После установки зависимостей командой npm install мы готовы к созданию связки через выполнение команды bundleup из package.json:

npm run bundleup

Эта команда создаст index.bundle.js в директории dist. Этот файл будет содержать скомпилированную (при помощи Babel) версию файла index.js, а также код из JS-библиотеки Chalk. Запустить эту связку вы можете как обычно:

node dist/index.bundle.js

Вывод, показанный на рис. 6.14, будет знакомым.

Для генерации JavaScript не нужно выбирать между Babel и tsc. Они могут успешно сосуществовать в одном проекте.

image

Противники TypeScript зачастую используют такой аргумент: «Если я буду писать на чистом JS, мне не потребуется использовать компилятор. Я смогу запустить JS-программу сразу после ее написания». Это абсолютно ошибочно, так как если вы не хотите игнорировать новейший синтаксис JS, представленный, начиная с версии 2015, потребуется процесс, который сможет компилировать код, написанный в современном JS, в код, который смогут понять все браузеры. Скорее всего, вы так или иначе будете использовать в своем проекте компилятор, будь то Babel, TypeScript или какой-либо другой.

Об авторах

Яков Файн является сооснователем двух IT-компаний: Farata Systems и SuranceBay. Он автор и соавтор таких книг, как Java Programming: 24-Hour Trainer, Angular Development with TypeScript1, Java Programming for Kids и др. Являясь чемпионом Java, провел множество классов и семинаров, посвященных веб- и Java-технологиям. Помимо этого, также был докладчиком на международных конференциях. Файн опубликовал более тысячи статей в своем блоге на yakovfain.com. В твиттере и инстаграме его можно найти по адресу @yfain. Он также публикует видео на YouTube.

Антон Моисеев является ведущим разработчиком в SuranceBay. Провел за разработкой корпоративных приложений более десяти лет, работая с Java и .NET. Имеет обширный опыт и фокусируется на развитии веб-технологий, реализующих лучшие методики слаженной работы фронтенда и бэкенда. Некоторое время проводил обучение по фреймворкам AngularJS и Angular. Периодически Антон делает посты в блоге antonmoissev.com. В твиттере вы можете найти его по адресу @antonmoiseev.

Более подробно с книгой можно ознакомиться на сайте издательства
» Оглавление
» Отрывок

Для Хаброжителей скидка 25% по купону — TypeScript

По факту оплаты бумажной версии книги на e-mail высылается электронная книга.
Теги:книга
Хабы: Блог компании Издательский дом «Питер» Профессиональная литература TypeScript
Всего голосов 5: ↑5 и ↓0 +5
Просмотры2.5K

Похожие публикации

Лучшие публикации за сутки

Информация

Дата основания
Местоположение
Россия
Сайт
piter.com
Численность
201–500 человек
Дата регистрации

Блог на Хабре