DevGang
Авторизоваться

Как добавить TypeScript в проект JavaScript

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

Сколько бы я ни практиковался, в продакшене продолжали появляться одни и те же ошибки: исключения cannot read property <> of undefined, знаменитая строка [Object object] и даже вызовы функций с недопустимым количеством параметров.

Более того, большинство кодовых баз, над которыми я работал, были действительно большими JavaScript-базами. Вот хорошая диаграмма того, как я себя чувствовал:

Мы можем сделать намного лучше!

В этом посте я не буду объяснять, почему TypeScript великолепен (и это так), и сосредоточусь на задачах, которые вам нужно выполнить, если вы хотите перенести свой обычный проект JavaScript в смешанный проект TypeScript.

К концу поста вы станете более счастливым человеком и сможете ответить на следующие вопросы:

  1. Как я могу добавить типы в свой проект JavaScript?
  2. Что такое TypeScript?
  3. Как я могу использовать TypeScript в проекте JavaScript?
  4. Что нужно сделать, чтобы преобразовать приложение JavaScript для поддержки TypeScript?
  5. Как я могу позаботиться о сборке и упаковке?
  6. Как мне позаботиться о линтинге?
  7. Как я могу «продать» TypeScript моей организации и разработчикам?

Как я могу добавить типы в свой проект JavaScript?

Vanilla JavaScript в настоящее время не поддерживает типы, поэтому для этого нам нужна какая-то абстракция поверх JavaScript.

Некоторые распространенные абстракции используют статическую проверку типов Facebook под названием flowи язык Microsoft под названием typescript.

В этом сообщении блога будет рассмотрено использование и добавление TypeScript в ваш проект JavaScript.

Что такое машинописный текст?

TypeScript - это типизированное надмножество JavaScript, которое компилируется в обычный JavaScript.

Если вы знаете javascript, вы уже на полпути.
Если вы знаете javascript, вы уже на полпути.

TypeScript состоит из нескольких частей. Первый - это язык TypeScript - это новый язык, содержащий все функции JavaScript. Ознакомьтесь со спецификациями для получения дополнительной информации.

Второй - компилятор TypeScript tsc(механизм системы типов), это механизм компиляции, который создает ts-файлы и выдает js-файлы.

Hello world в TypeScript

В качестве примера, вот шаги, которые вам нужно предпринять, чтобы написать свое первое приложение TypeScript:

  1. установить TypeScript с помощью npm i typescript
  2. создайте папку с именем exampleи cd (в вашем терминале)
  3. создать файл с именем hello.world.ts
  4. напишите в нем следующий код:
Hello world в TypeScript - моя первая программа на TypeScript!
const firstWords:string = "hello world"
console.info(firstWords);

а затем сохраните его.

5. запустите команду tsc для запуска компилятора TypeScript в текущей папке.

6. обратите внимание, что у вас есть файл hello.js, который теперь можно запустить:)

7. запустить node ./hello.js

Как я могу использовать TypeScript в проекте JavaScript?

Есть несколько стратегий для выполнения этой «миграции» (с точки зрения компании и кода). Я перечислил их ниже по их «стоимости» и по степени ценности.

Я бы посоветовал начать с «поддержки приложений TS» и двигаться дальше после того, как вы доказали ценность для своей команды разработчиков.

Процесс миграции TypeScript  выполняется итеративно, только если вы подтверждаете ценность.
Процесс миграции TypeScript выполняется итеративно, только если вы подтверждаете ценность.

Подход «маленький шаг для человека» - добавление поддержки TS для существующих приложений

Один маленький шаг для разработчика.
Один маленький шаг для разработчика.

Мое первое предложение - создать смесь двух языков в одном проекте, а затем написать весь «будущий» код на TypeScript.

Комбинация двух языков в одном проекте сначала звучит ужасно, но работает достаточно хорошо, поскольку TS был построен для постепенного использования. Сначала его можно использовать как JS с файлами .ts и странными строками импорта.

В этой стратегии мы будем компилировать перенесенные файлы TypeScript и просто копировать файлы JavaScript в папку вывода.

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

Я настоятельно рекомендую начать с этого шага, а затем повторить его вместе со своей командой, прежде чем двигаться дальше. Чтобы быстро узнать, как это сделать, прокрутите вниз до раздела The steps to convert a javascript application to support typescript.

Подход open for business - добавление поддержки TS для существующих библиотек.

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

Это можно сделать двумя способами:

Первый способ предполагает использование файлов объявлений. Простое добавление файлов d.ts помогает компилятору TS проверять тип существующего кода JavaScript и обеспечивает поддержку автозаполнения в вашей среде IDE.

Это самый «дешевый» вариант, так как он вообще не требует изменения кода библиотеки. Это также дает вам максимальную мощность и поддержку типов в вашем будущем коде.

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

Скелет - шаг в будущее

Каркас Typescript - залог светлого будущего!
Каркас Typescript - залог светлого будущего!

Я предполагаю, что большинство разработчиков «ленивы» и обычно запускают свое приложение с копирования из каркаса (который обычно содержит журналы, показатели, конфигурацию и так далее).

Этот шаг поможет вам проложить свой путь в светлое будущее, создав «официальный» каркас вашей компании. Это будет 100% TS, и устаревший каркас JS, если он существует.

Этот стартовый узел typescript - действительно хороший первый проект для начала.

Комплексный подход - преобразование полной кодовой базы из JS в TS

Этот вариант требует полной перезаписи кода JavaScript на TypeScript.

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

Вы можете выполнить такую ​​перезапись (это долгий процесс) следующим образом:

  1. Определите четкие типы для бизнес-логики, API и HTTP вашего приложения.
  2. Используйте пакеты @types для всех библиотек в вашем package.json. Большинство существующих библиотек поддерживают TS, и в этом процессе я предлагаю перенести их одну за другой (просто добавляя @types/<package_name> в свой файл package.json).
  3. Преобразуйте логические компоненты приложения в порядке их важности. Чем уникальнее бизнес-логика, тем лучше.
  4. Преобразуйте части ввода-вывода вашего приложения, уровни базы данных, очереди и так далее.
  5. Преобразуйте свои тесты.

Имейте в виду, что есть автоматизированные инструменты, призванные облегчить этот процесс, например ts-migrate от команды Airbnb.

Он решает эту проблему с другой точки зрения и конвертирует все файлы в TypeScript. Это также позволяет постепенно улучшать (как указано в шагах выше), в то время как вся кодовая база является TypeScript с первого дня.

Как преобразовать приложение JavaScript для поддержки TypeScript.

Установить машинописный текст

запустить: npm install typescript.

Конфигурационный файл Typescript

Добавьте файл конфигурации TypeScript, который можно создать с помощью команды tsc --init в вашем интерфейсе командной строки.

Вот пример того, как выглядела наша первоначальная конфигурация:

{
 "compilerOptions": {
   "target": "esnext",
   "module": "commonjs",
   "allowJs": true,
   "checkJs": false,
   "outDir": "dist",
   "rootDir": ".",
   "strict": false,
   "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
   "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */
   "declaration": true, /* Generates corresponding '.d.ts' file. */
   "strictNullChecks": true,
   "resolveJsonModule": true,
   "sourceMap": true,
   "baseUrl": ".",
   "paths": {
    "*": [
      "*",
      "src/*",
      "src/setup/*",
      "src/logic/*",
      "src/models/*",
      "config/*"
    ]
  },
 },
  "exclude": ["node_modules", "dist"],
  "include": [
    "./src",
    "./test",
    "./*",
    "./config" 
  ]
}

Несколько замечаний выше:

  1. Мы читаем все файлы в каталоге src или test или config(используя флаг include).
  2. Мы принимаем файлы JavaScript в качестве входных данных (используя флаг allowJs).
  3. Мы испускаем все выходные файлы в build(используя outDirflag).

Создайте свой первый файл .TS в своем проекте

Я рекомендую начать с добавления простого файла TypeScript (или изменения действительно простого файла JS на файл TS) и развертывания. Выполняйте эту миграцию поэтапно.

Позаботьтесь о своем файле package.json

Вот как выглядит package.json до и после:

Перед
{
  "scripts": {
    "start": "node ./application.js",
    "mocha": "mocha --recursive --reporter spec -r test/bootstrap.js",
    "test": "npm run mocha -- test/ -r test/integration/bootstrap.js", 
  }
}
После
{
  "scripts": {
    "start": "node ./dist/application.js",
    "build-dist": "./node_modules/typescript/bin/tsc",
    "mocha": "mocha --recursive --reporter spec -r ./dist/test/bootstrap.js",
    "test": "npm run mocha -- ./dist/test/ -r ./dist/test/integration/bootstrap.js"
  }
}

Как видите, большинство изменений касалось добавления префикса dist к большинству наших команд сборки. Мы также добавили скрипт build-dist, который компилирует нашу кодовую базу и перемещает все файлы в специальную папку с именем dist.

Добавить поддержку карты источника

Одна из больших проблем при добавлении TypeScript в ваш проект заключается в том, что вы добавляете слой косвенности между кодом, который вы пишете, и кодом, который фактически выполняется в рабочей среде (так как .ts транспилируется в .js во время выполнения).

Например, представьте следующую программу TypeScript:

const errorMessage: string = "this is bad"

throw new Error(a)

Когда мы запустим его, он выдаст следующую трассировку стека:

Подождите! но в нашем машинописном коде всего 2 строки!
Error: this is bad
    at Object.<anonymous> (/Users/dorsev/work/git/example/hello.js:3:7)

Это проблематично, поскольку наша кодовая база содержит только файлы .ts. А поскольку большая часть производственного кода содержит сотни строк, правильный перевод этих чисел и файлов займет действительно много времени.

К счастью для нас, есть решение этой проблемы, называемое поддержкой исходной карты!

Это позволяет нам гарантировать, что трассировки стека будут иметь правильные имена файлов .ts и номера строк, как мы привыкли:)

Это можно сделать, запустив, npm install source-map-support а затем добавив следующую строку в первые строки вашего приложения:

require('source-map-support').install();

Теперь код выглядит так:

hello.world.ts
require('source-map-support').install();
const a:string = "this is bad"
throw new Error(a)

И когда мы его компилируем, мы запускаем tsc --sourcemap hello.ts. Теперь мы получаем следующую трассировку стека, и это здорово:)  

Error: this is bad
    at Object.<anonymous> (/Users/dorsev/work/git/example/hello.ts:3:7)

В последних версиях nodejs это поддерживается изначально с помощью флага --enable-source-maps.

Как заботиться о сборке и упаковке

Давайте просто рассмотрим изменения до и после в нашем файле конфигурации сборки.

Вот так наш файл .travis выглядел раньше (упрощенная версия):

Упрощенный .travis перед машинописным текстом
jobs:
  include:
  - &build-and-publish
    before_script:
    - npm install --no-optional --production
    - npm prune --production
    before_deploy:
     - XZ_OPT=-0 tar --exclude=.git --exclude=reports.xml --exclude=${ARTIFACTS_MAIN_DIR}
       --exclude=.travis.yml --exclude=test -cJf "${ARTIFACTS_PATH}/${REPO_NAME}".tar.xz * .??*
  
  - &test
    before_script:
     - npm install --no-optional
    script:
     - echo "Running tests"
     - npm run lint && npm test

И вот как он выглядел после этого:

Упрощенный .travis после машинописного текста
jobs:
  include:
  - &build-and-publish
    before_script:
    - npm install --no-optional --production
    - npm run build-dist  # Build dist folder
    - npm prune --production
    before_deploy:
     - cp -rf config/env-templates ./dist/config/
     - cp -rf node_modules ./dist/
     - cd dist
     - XZ_OPT=-0 tar --exclude=.git --exclude=reports.xml --exclude=${ARTIFACTS_MAIN_DIR} --exclude=.travis.yml --exclude=test -cJf "${REPO_NAME}.tar.xz" *
     - mv ${REPO_NAME}.tar.xz "../${ARTIFACTS_PATH}"
     - cd ..

  - &test
    before_script:
     - npm install --no-optional
     - npm run build-dist
    script:
     - echo "Running tests"
     - npm run lint && npm test

Обратите внимание, что большинство изменений касается «упаковки» файла tar.xz и выполнения команды build-dist перед доступом к папке dist.

Как мне позаботиться о линтинге?

Доступно несколько вариантов линтинга.

Первым решением, которое мы использовали, было tsfmt,   но позже мы отказались от него, потому что оно требует от вас поддержки двух отдельных конфигураций для вашего проекта (для TypeScript через sfmt и отдельный для JavaScript, с помощью eslint). Проект также выглядит устаревшим.

Затем мы нашли TSLint,  который перенаправил нас на плагин eslint для TypeScript. Затем мы настроили его следующим образом:

Это был наш eslintrc.js:

module.exports = {
    rules: {
        indent: [2, 2, {
            SwitchCase: 1
        }],
        'no-multi-spaces': 2,
        'no-trailing-spaces': 2,
        'space-before-blocks': 2,
    },
    overrides: [{
        files: ['**/*.ts'],
        parser: '@typescript-eslint/parser',
        plugins: ['@typescript-eslint'],
        extends: ['plugin:@typescript-eslint/eslint-recommended', 'plugin:@typescript-eslint/recommended']
    }]
}

Который мы настроили для запуска с помощью команды lint-fix в нашем package.json который выглядит следующим образом:

{
    "scripts": {
        "lint-fix": "node_modules/.bin/eslint . --fix"
    },
    "pre-commit": ["lint-fix"]
}

Как «продать» машинописный текст вашей команде разработчиков

Я считаю, что одним из наиболее важных аспектов внедрения TypeScript в вашу организацию является «pitch» и то, как вы представляете его своей команде разработчиков.

Вот презентация, которую мы представили внутри компании, которая вращалась вокруг следующих тем:

  1. Объясните, почему мы считаем TypeScript крутым
  2. Что такое TypeScript
  3. Некоторые базовые примеры кода. Главное в этой части - не «обучать» 100% TypeScript, поскольку люди будут делать это сами. Вместо этого дайте людям почувствовать, что они могут читать и писать TypeScript и что кривая обучения не так уж и сложна.
  4. Расширенные примеры кода, такие как типы Union и алгебраические типы данных, которые предоставляют огромные возможности JS-разработчику. Это настоящие удовольствия, помимо типизированного языка и компилятора, который привлечет к нему ваших разработчиков.
  5. Как начать пользоваться. Поощряйте людей загрузить IDE vs-code и добавить аннотацию ( // @ ts-check), чтобы они могли начать видеть волшебство! В нашей компании мы заранее подготовили некоторые действительно крутые ошибки, которые выявляют ts-check, и мы провели живую демонстрацию (2-3 минуты), чтобы показать, насколько быстро компилятор TypeScript может помочь им с помощью документов JS с аннотациями типов или ts-check).
  6. Погрузитесь в некоторые особенности. Объясните файлы ts.d и @types packages которые являются одними из вещей, которые вы действительно встретите в самом начале TypeScript программы.
  7. Живой пиар от вашей работы. Мы показали PR, который мы создали на раннем этапе, и призвали людей просмотреть его и попробовать на себе.
  8. Поделитесь классными ресурсами. В сети много контента, и сложно отличить хорошее от плохого. Копайте глубже и постарайтесь найти качественный контент об инструментах, которые вы используете и которые вам нужны. 
  9. Создайте публичный пул-реквест. Я рекомендую попытаться получить как можно больше поддержки для его утверждения.
Добавление typescript в проект!Ура!&nbsp;
Добавление typescript в проект!Ура! 

10. Создайте в своей организации положительный отзыв об изменениях!

Я настоятельно рекомендую настроить этот список в соответствии с вашей командой, стандартами и ограничениями по времени.
Я настоятельно рекомендую настроить этот список в соответствии с вашей командой, стандартами и ограничениями по времени.

Вывод

Typescript супер! Если вы пишете программное обеспечение производственного уровня, а бизнес-требования и доступность высоки, я настоятельно рекомендую вам попробовать Typescript.

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

Создайте короткий цикл обратной связи и ценностное предложение. Трудно «продать» новый язык вашей команде и руководству, поскольку это требует времени и ресурсов.

Поэтому разработайте процесс миграции с короткими циклами обратной связи и попытайтесь определить четкие KPI (меньше ошибок в производстве, более легкое время рефакторинга и т. д.) И убедитесь, что ценностное предложение для вашего варианта использования постоянно оправдывается, пока оно не станет де- факто стандарт.  

Сделайте учебные ресурсы доступными. 

Источник:

#JavaScript #TypeScript #Машинное обучение
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться