Выживание в экосистеме TypeScript: написание безопасного для типов (ish) кода JavaScript

Источник на Github: Демонстрация TypeScript

Небольшое примечание, прежде чем мы перейдем к этому: все примеры в этом посте используют TypeScript v2.9.1. Если вы видите другое поведение, проверьте свою версию. Время от времени я буду стараться обновлять примеры с помощью обновлений TypeScript.

Вступление

О чем конкретно этот пост? Это начало работы с постом TypeScript? Вид. Я называю это началом работы с предположениями, больше руководством по выживанию. Я собираюсь сделать следующие предположения: вы знакомы с JavaScript и связанной с ним экосистемой и знакомы по крайней мере с одним языком со статической типизацией (Java, Scala, Swift…). Я не буду ничего объяснять по экосистеме JavaScript и не буду подробно рассказывать о функциях TypeScript, которые являются интуитивно понятными и / или совместимыми с другими языками со статической типизацией. Вы заметите, что многие нотации TypeScript будут очень похожи на Java или C #. Однако я расскажу о тех областях, в которых TypeScript ведет себя не так, как вы могли бы предположить, исходя из этих языков.

Я описываю это скорее как руководство по выживанию, потому что мы будем уделять особое внимание особенностям и несоответствиям в TypeScript, которые, как я видел, вызывают у людей наибольшие проблемы. Из-за интеграции TypeScript с JavaScript вы, как правило, не можете рассчитывать на ту же безопасность, которую получаете от других статически типизированных языков, кроме того, есть сложности с интеграцией с JavaScript, которые вы должны учитывать.

Рассмотрев некоторые из наиболее распространенных проблем с TypeScript, мы поговорим о некоторых функциях, которые являются уникальными для TypeScript или, как мне кажется, недостаточно используются в TypeScript. Мы рассмотрим особенности, которые дадут вам большую выразительность над вашими типами, что позволит вам более точно выражать то, что ваши приложения делают через систему типов. Чем точнее вы сможете статически выразить то, что делает ваше приложение, тем более полезным станет компилятор.

Разрушение зверя

Так начался один мега-пост о множестве вещей, которые я хотел осветить с помощью TypeScript. Это стало немного громоздко, так что я разделил вещи. Теперь каждый пост будет меньшим, более управляемым фрагментом, посвященным какой-то конкретной теме, связанной с TypeScript.

Что такое TypeScript?

Несмотря на то, что это не просто пошаговое руководство по TypeScript, я хочу дать определение TypeScript в некотором практическом смысле. Я считаю, что практическое использование TypeScript немного более тонкое, чем официальное определение. Прежде чем я начну разбирать его, вот официальное определение TypeScript:

TypeScript - это статически типизированный надмножество JavaScript - typescirptlang.org

На практике я не считаю, что это определение точно определяет, как вы должны думать о TypeScript. Когда вы впервые загружаете TypeScript и начинаете компилировать код, я думаю, что лучше всего думать о TypeScript как о занимающем то же место в вашем рабочем процессе, что и ESLint. На самом деле это, вероятно, даже не такой большой актив, как ESLint. Не надейтесь на то, что он идеален, в лучшем случае он укажет на несколько областей, в которых ваши типы могут не совпадать и, следовательно, могут вызвать ошибки. Он многое упустит. Его поведение по умолчанию не делает его хорошим инструментом для обеспечения безопасности типов в вашем коде.

Я думаю, что TypeScript имеет два определения в зависимости от того, как он настроен и как вы его используете:

  1. Как слой линтинга поверх вашего JavaScript, который поможет вам найти подозрительный код.
  2. Как собственный язык программирования, который компилируется в JavaScript (больше в соответствии с официальным

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

Зачем мне использовать TypeScript?

Добавление системы типов в ваш JavaScript дает много преимуществ. По мере того, как JavaScript и Интернет в целом эволюционировали от небольшого добавления некритичных изюминок к взаимодействиям с пользователем на статических веб-страницах и превратились в основу больших приложений со сложной бизнес-логикой, недостатки динамизма JavaScript стали очевидны. Намного проще управлять большими кодовыми базами, когда система типов обеспечивает гарантии между разными частями кода, разными файлами, разными модулями. Я говорю о гарантиях времени компиляции. Критические ошибки появляются раньше и носят более конкретный характер. Ошибка компилятора обычно сообщает вам, где что-то пошло не так, а что именно пошло не так. Ошибка во время выполнения сопровождается трассировкой стека, которая может быть лишь признаком проблемы, а не реальной основной проблемой. Ошибки времени выполнения часто связаны с тем, что детективная работа тратится на значительное время.

В форме легко усваиваемого списка некоторые из преимуществ использования TypeScript в вашем проекте JavaScript:

  1. Выявите потенциальные ошибки на ранних этапах цикла разработки.
  2. Документация - почти каждый разработчик должен лучше документировать свой код, типы, по крайней мере, сообщают о каком-то контракте, которому могут следовать другие разработчики или даже вы в будущем.
  3. Управление большими базами кода. Чем больше увеличивается база кода, тем больше необходимо иметь сильные контракты между различными частями кода, эти контракты принимают форму типов. Сильные типы также упрощают рефакторинг.
  4. Упростить работу в команде - это результат двух предыдущих. Чем сильнее контракты в коде, тем легче разным разработчикам входить и выходить из кодовой базы без непреднамеренного нарушения работы.

С какими проблемами я столкнусь?

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

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

  1. Он добавляет дополнительную экосистему к тому, что я уже использую.
  2. Это что-то новое, и у меня есть функции, которые нужно отправить. Отстаивать идею о том, что краткосрочное замедление темпов роста приведет к долгосрочному повышению эффективности, в некоторых условиях сложно.
  3. Типовые ошибки могут быть несовместимыми.
  4. Определения типов и ОпределенноТипед.
  5. Конфигурация кардинально меняет свое поведение.

Как только мы овладеем этим TypeScript, он станет ценным ресурсом, который сделает наши проекты JavaScript менее подверженными ошибкам, более простыми в обслуживании и более быстрыми для рефакторинга.

Подготовка к настройке

Форма этого поста больше похожа на семинар. Он предназначен для того, чтобы вы могли работать вместе и видеть вещи в действии. Итак, я собираюсь начать с нуля. Я начну с этих команд из ничего или из окна своего терминала.

$ mkdir typescript-demo
$ cd typescript-demo
$ npm init
$ git init
$ touch .gitignore
$ touch tsconfig.json
$ mkdir src

Итак, у меня появился новый каталог. У меня есть package.json и tsconfig.json (пустой). У меня также есть каталог, в котором мы можем написать код (src).

Следующее, что я собираюсь сделать, это установить TypeScript.

$ npm install --save-dev typescript

Теперь, когда у нас есть локальная (для нашего проекта) копия TypeScript, я собираюсь настроить свой package.json со сценариями для запуска TypeScript. Мы собираемся сохранить эту самую ваниль и наращивать.

{
    "name": "typescript-demo",
    "version": "1.0.0",
    "description": "",
    "scripts": {
        "clean": "rm -rf build",
        "prebuild": "npm run clean",
        "build": "tsc",
        "test": "echo \"Error: no test specified\" && exit 1"
    },
    "author": "Kevin B. Greene",
    "license": "Apache-2.0",
    "devDependencies": {
        "typescript": "^2.8.3"
    }
}

Все, что я действительно здесь сделал, так это сделал так, чтобы команда npm run build запускала tsc (компилятор TypeScript).

Отсюда нам нужно настроить нашу начальную конфигурацию для TypeScript, что означает, что мы переходим к tsconfig.json.

{
    "compilerOptions": {
        "target": "es2015",
        "module": "commonjs",
        "moduleResolution": "node",
        "pretty": true,
        "removeComments": true,
        "rootDir": "./src",
        "outDir": "./build"
    },
    "exclude": [ "node_modules" ]
}

Опять же, это довольно минимальная конфигурация. Важным элементом является то, что мы строим из каталога «./src» в каталог «./build».

Последнее, что мы собираемся сделать, это добавить файл для написания нашего кода.

$ touch src/index.ts

Круто, пустой файл, мы готовы написать код.

Выбери свое приключение

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

  1. Строгие флаги компилятора
  2. Интерфейсы и структурная типизация
  3. Работа с типами и определениями типов
  4. Типовые гвардейцы и дискриминируемые союзы
  5. Брендинг и тегирование
  6. Функциональные перегрузки
  7. Оператор «keyof» (скоро)

Дальнейшее чтение