- PVSM.RU - https://www.pvsm.ru -

Обзор ts-migrate — инструмента для перевода крупномасштабных проектов на TypeScript

В Airbnb для фронтенд-разработки официально применяется TypeScript (TS). Но процесс внедрения TypeScript и перевода на этот язык зрелой кодовой базы, состоящей из тысяч JavaScript-файлов, это — не дело одного дня. А именно, внедрение TS происходило в несколько этапов. Сначала это было предложение, через некоторое время язык начали применять во множестве команд, потом внедрение TS вышло в бета-фазу. В итоге же TypeScript стал официальным языком фронтенд-разработки Airbnb. Подробнее о процессе внедрения TS в Airbnb рассказано здесь [1].

Обзор ts-migrate — инструмента для перевода крупномасштабных проектов на TypeScript - 1 [2]

Этот материал посвящён описанию процессов перевода больших проектов на TypeScript и рассказу о специализированном инструменте, ts-migrate, разработанном в Airbnb.

Стратегии миграции

Перевод крупномасштабного проекта с JavaScript на TypeScript — это сложная задача. Мы, приступая к её решению, исследовали две стратегии перехода с JS на TS.

▍1. Гибридная стратегия миграции

При таком подходе осуществляется постепенный, пофайловый перевод проекта на TypeScript. В ходе этого процесса редактируют файлы, исправляют ошибки типизации и работают так до тех пор, пока на TS не будет переведён весь проект. Параметр allowJS [3] позволяет иметь в проекте и TypeScript-файлы и JavaScript-файлы. Благодаря этому такой подход к переводу JS-проектов на TS вполне жизнеспособен.

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

▍2. Всеобъемлющая стратегия миграции

При таком подходе берётся проект, написанный исключительно на JavaScript, или такой, часть которого написана на TypeScript, и полностью преобразовывается в TypeScript-проект. При этом понадобится использовать тип any и комментарии @ts-ignore, что позволит проекту компилироваться без ошибок. Но со временем код можно отредактировать и перейти к использованию более подходящих типов.

У всеобъемлющей стратегии миграции на TypeScript есть несколько серьёзных преимуществ перед гибридной стратегией:

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

Если учесть вышесказанное, то может показаться, что всеобъемлющая миграция по всем показателям превосходит гибридную миграцию. Но всеобъемлющий перевод зрелой кодовой базы на TypeScript — это очень трудная задача. Для её решения мы решили прибегнуть к скриптам для модификации кода, к так называемым «кодмодам» (codemods [4]). Когда мы только начали перевод проекта на TypeScript, делая это вручную, мы обратили внимание на повторяющиеся операции, которые можно было бы автоматизировать. Мы написали кодмоды для каждой из таких операций и объединили их в единый конвейер миграции.

Опыт подсказывает нам, что нельзя быть на 100% уверенным в том, что после автоматического перевода проекта на TypeScript в нём не будет ошибок. Но мы выяснили, что комбинация шагов, описанная ниже, позволила нам добиться наилучших результатов и, в итоге, получить TypeScript-проект, лишённый ошибок. Мы, используя кодмоды, смогли перевести на TypeScript проект, содержащий более 50000 строк кода и представленный более чем 1000 файлами. На это у нас ушёл один день.

На основе конвейера, показанного на следующем рисунке, мы создали инструмент ts-migrate.

Обзор ts-migrate — инструмента для перевода крупномасштабных проектов на TypeScript - 2

Кодмоды ts-migrate

В Airbnb значительная часть фронтенда написана с использованием React [5]. Именно поэтому некоторые части кодмодов имеют отношение к концепциям, специфичным для React. Средство ts-migrate может быть использовано и с другими библиотеками или фреймворками, но это потребует его дополнительной настройки и тестирования.

Обзор процесса миграции

Пройдёмся по основным шагам, которые нужно выполнить для перевода проекта с JavaScript на TypeScript. Поговорим и о том, как именно реализованы эти шаги.

▍Шаг 1

Первое, что создают в каждом TypeScript-проекте, это — файл tsconfig.json. Ts-migrate может, если нужно, сделать это самостоятельно. Существует стандартный шаблон этого файла. Кроме того, имеется система проверок, которая позволяет обеспечить единообразную конфигурацию всех проектов. Вот пример базовой конфигурации:

{
  "extends": "../typescript/tsconfig.base.json",
  "include": [".", "../typescript/types"]
}

▍Шаг 2

После того, как файл tsconfig.json находится там, где он должен быть, выполняется переименование файлов с исходным кодом. А именно, расширения .js/.jsx меняются на .ts/.tsx. Этот шаг очень легко автоматизировать. Это позволяет избавиться от большого объёма ручного труда.

▍Шаг 3

А теперь пришло время запускать кодмоды! Мы называем их «плагинами». Плагины для ts-migrate — это кодмоды, у которых есть доступ к дополнительной информации через языковой сервер TypeScript. Плагины принимают на вход строки и выдают изменённые строки. Для выполнения трансформаций кода может быть использован набор инструментов jscodeshift [6], API TypeScript, средства обработки строк или другие инструменты для модификации AST.

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

Обзор пакетов, из которых состоит ts-migrate

Мы разделили ts-migrate на 3 пакета:

Поступив так, мы смогли отделить логику трансформации кода от ядра системы и смогли создать множество конфигураций, рассчитанных на решение разных задач. Сейчас у нас есть две основных конфигурации: migration [10] и reignore [11].

Цель применения конфигурации migration заключается в переводе проекта с JavaScript на TypeScript. А конфигурация reignore применяется для того чтобы сделать возможной компиляцию проекта, просто игнорируя все ошибки. Эта конфигурация полезна в случаях, когда имеется большая кодовая база и с ней выполняют различные действия наподобие следующих:

  • Обновление версии TypeScript.
  • Внесение в код серьёзных изменений или рефакторинг кодовой базы.
  • Улучшение типов некоторых широко используемых библиотек.

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

Обе конфигурации работают на сервере ts-migrate-server, который состоит из двух частей:

  • TSServer [12]: эта часть сервера очень похожа на то, что используется [13] в VSCode для организации взаимодействия редактора и языкового сервера. Новый экземпляр языкового сервера TypeScript запускается в отдельном процессе. Инструменты разработки взаимодействуют с ним, используя языковой протокол [14].
  • Средство для выполнения миграции [15]: это — код, который выполняет процесс миграции и координирует этот процесс. Это средство принимает следующие параметры:

interface MigrateParams {
  rootDir: string;          // Путь к корневой директории.
  config: MigrateConfig;    // Настройки миграции, включая список 
                            // плагинов.
  server: TSServer;         // Экземпляр форка TSServer.
}

Это средство выполняет следующие действия:

  1. Разбор [16] файла tsconfig.json.
  2. Создание [17] .ts-файлов с исходным кодом.
  3. Отправка [18] каждого файла языковому серверу TypeScript для диагностики этого файла. Есть три типа диагностики, которые даёт нам компилятор: semanticDiagnostics, syntacticDiagnostics и suggestionDiagnostics. Мы используем эти проверки для нахождения в исходном коде проблемных мест. Основываясь на уникальном коде диагностики и на номере строки в файле, мы можем идентифицировать возможный тип проблемы и применить необходимые модификации кода.
  4. Обработка [19] каждого файла всеми плагинами. Если текст в файле изменился по инициативе плагина, мы обновляем содержимое [20] исходного файла и уведомляем языковой сервер о том, что файл был изменён.

Примеры использования ts-migrate-server можно найти в пакете examples [21] или в пакете main [22]. В ts-migrate-example, кроме того, содержатся базовые примеры плагинов [23]. Они делятся на 3 основные категории:

  • Плагины [24], основанные на jscodeshift.
  • Плагины [25], основанные на абстрактном синтаксическом дереве (AST, Abstract Syntax Tree) TypeScript.
  • Плагины [26], основанные на обработке текста.

В репозитории имеется набор примеров, направленных на демонстрацию процесса создания простых плагинов всех этих видов. Там же показано и их использование в комбинации c ts-migrate-server. Вот пример конвейера миграции [27], преобразующего код. На его вход поступает такой код:

function mult(first, second) {
  return first * second;
}

А выдаёт он следующее:

function tlum(tsrif: number, dnoces: number): number {
  console.log(`args: ${arguments}`);
  return tsrif * dnoces;
}

В этом примере ts-migrate выполнил 3 трансформации:

  1. Обратил порядок символов во всех идентификаторах: first -> tsrif.
  2. Добавил сведения о типах в объявление функции: function tlum(tsrif, dnoces) -> function tlum(tsrif: number, dnoces: number): number.
  3. Добавил в код строку console.log(‘args:${arguments}’);

Плагины общего назначения

Настоящие плагины расположены в отдельном пакете — ts-migrate-plugins [9]. Взглянем на некоторые из них. У нас имеются два плагина, основанных на jscodeshift: explicitAnyPlugin и declareMissingClassPropertiesPlugin. Набор инструментов jscodeshift [6] позволяет преобразовывать AST в обычный код, используя пакет recast [28]. Мы можем, воспользовавшись функцией toSource(), напрямую обновлять исходный код, содержащийся в наших файлах.

Плагин explicitAnyPlugin [29] берёт с языкового сервера TypeScript информацию обо всех ошибках semanticDiagnostics и о строках, в которых выявлены эти ошибки. Затем в эти строки добавляется аннотация типа any. Этот подход позволяет исправлять ошибки, так как использование типа any позволяет избавиться от ошибок компиляции.

Вот пример кода до обработки:

const fn2 = function(p3, p4) {}
const var1 = [];

Вот — тот же код, обработанный плагином:

const fn2 = function(p3: any, p4: any) {}
const var1: any = [];

Плагин declareMissingClassPropertiesPlugin [30] берёт все диагностические сообщения с кодом ошибки 2339 (можете догадаться о том, что значит [31] этот код?) и, если может найти объявления классов с пропущенными идентификаторами, добавляет их в тело класса с аннотацией типа any. Из названия плагина можно сделать вывод о том, что он применим только к ES6-классам [32].

Следующая категория плагинов основана на AST TypeScript. Обрабатывая AST, мы можем сгенерировать массив обновлений, которые нужно внести в файл с исходным кодом. Описания этих обновлений выглядят так:

type Insert = { kind: 'insert'; index: number; text: string };
type Replace = { kind: 'replace'; index: number; length: number; text: string };
type Delete = { kind: 'delete'; index: number; length: number };

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

Взглянем на следующую пару плагинов, основанных на AST. Это — stripTSIgnorePlugin и hoistClassStaticsPlugin.

Плагин stripTSIgnorePlugin [33] — это первый плагин, используемый в конвейере миграции. Он убирает из файла все комментарии @ts-ignore (эти комментарии позволяют нам сообщать компилятору о том, что он должен игнорировать ошибки, происходящие в следующей строке). Если мы занимаемся переводом на TypeScript проекта, написанного на JavaScript, то этот плагин не будет выполнять никаких действий. Но если речь идёт о проекте, который частично написан на JS, а частично — на TS (несколько наших проектов пребывали в подобном состоянии), то это — первый шаг миграции, без которого нельзя обойтись. Только после удаления комментариев @ts-ignore компилятор TypeScript сможет выдавать диагностические сообщения об ошибках, которые нужно исправлять.

Вот код, поступающий на вход этого плагина:

const str3 = foo
  ? // @ts-ignore
    // @ts-ignore comment
    bar
  : baz;

Вот что получается на выходе:

const str3 = foo
  ? bar
  : baz;

После избавления от комментариев @ts-ignore мы запускаем плагин hoistClassStaticsPlugin [34]. Он проходится по всем объявлениям классов. Плагин определяет возможность поднятия идентификаторов или выражений и выясняет, поднята ли уже некая операция присвоения на уровень класса.

Для того чтобы обеспечить высокую скорость разработки и избежать вынужденных возвратов к предыдущим версиям проекта, мы снабдили каждый плагин [35] и ts-migrate [36] набором модульных тестов.

Плагины, имеющие отношение к React

Плагин reactPropsPlugin [37], основанный на этом [38] замечательном инструменте, преобразует информацию о типах из формата PropTypes в объявления типов TypeScript. С помощью этого плагина нужно обрабатывать исключительно .tsx-файлы, содержащие хотя бы один React-компонент. Этот плагин ищет все объявления PropTypes и пытается разобрать их с использованием AST и простых регулярных выражений наподобие /number/, или с привлечением более сложных регулярных выражений вроде /objectOf$/ [39]. Когда обнаруживается React-компонент (функциональный, или основанный на классах), он трансформируется в компонент, в котором для входных параметров (props) используется новый тип: type Props = {…};.

Плагин reactDefaultPropsPlugin [40] отвечает за реализацию в React-компонентах паттерна defaultProps [41]. Мы используем особый тип, представляющий входные параметры, которым заданы значения, применяемые по умолчанию:

type Defined<T> = T extends undefined ? never : T;
type WithDefaultProps<P, DP extends Partial<P>> = Omit<P, keyof DP> & {
  [K in Extract<keyof DP, keyof P>]:
    DP[K] extends Defined<P[K]>
      ? Defined<P[K]>
      : Defined<P[K]> | DP[K];
};

Мы пытаемся найти входные параметры, которым назначены значения, применяемые по умолчанию, после чего объединяем их с типом, описывающим входные параметры компонента, созданным на предыдущем шаге.

В экосистеме React широко применяются концепции [42] состояния и жизненного цикла компонентов. Мы решаем задачи, относящиеся к этим концепциям, в следующей паре плагинов. Так, если компонент имеет состояние, то плагин reactClassStatePlugin [43] генерирует новый тип (type State = any;), а плагин reactClassLifecycleMethodsPlugin [44] аннотирует методы жизненного цикла компонента соответствующими типами. Функционал этих плагинов может быть расширен, в том числе — за счёт оснащения их возможностью заменять any на более точные типы.

Эти плагины можно улучшать, в частности, за счёт расширения поддержки типов для состояния и свойств. Но и их существующие возможности, как оказалось, являются хорошей отправной точкой для реализации нужного нам функционала. Мы, кроме того, не работаем тут с React-хуками [45], та как в начале миграции в нашей кодовой базе использовалась старая версия React, не поддерживающая хуки.

Проверка правильности компиляции проекта

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

После всех трансформаций и модификаций наш код может оказаться неоднородно отформатированным, что способно привести к тому, что некоторые проверки кода линтером выявят ошибки. В кодовой базе нашего фронтенда используется система, основанная на Prettier и ESLint. А именно, Prettier [46] применяется для автоматического форматирования кода, а ESLint [47] помогает проверять код на предмет его соответствия рекомендованным подходам к разработке. Всё это позволяет нам быстро справляться с проблемами форматирования кода, появившимися в результате ранее выполненных действий, просто воспользовавшись соответствующим плагином [48]eslintFixPlugin.

Последним шагом конвейера миграции является проверка того, что решены все проблемы компиляции TypeScript-кода. Для того чтобы находить и исправлять потенциальные ошибки плагин tsIgnorePlugin [49] берёт сведения семантической диагностики кода и номера строк, а после этого добавляет в код комментарии @ts-ignore с объяснениями ошибок. Например, это может выглядеть так:

// @ts-ignore ts-migrate(7053) FIXME: No index signature with a parameter of type 'string...
const { field1, field2, field3 } = DATA[prop];
// @ts-ignore ts-migrate(2532) FIXME: Object is possibly 'undefined'.
const field2 = object.some_property;

Мы оснастили систему и поддержкой синтаксиса JSX:

{*
// @ts-ignore ts-migrate(2339) FIXME: Property 'NORMAL' does not exist on type 'typeof W... */}
<Text weight={WEIGHT.NORMAL}>
  some text
</Text>
<input
  id="input"
  // @ts-ignore ts-migrate(2322) FIXME: Type 'Element' is not assignable to type 'string'.
  name={getName()}
/>

То, что в нашем распоряжении имеются осмысленные сообщения об ошибках, упрощает исправление ошибок и поиск фрагментов кода, на которые нужно обратить внимание. Соответствующие комментарии, в комбинации с $TSFixMe, позволяют нам собирать ценные данные о качестве кода и находить потенциально проблемные фрагменты кода. $TSFixMe — это созданный нами псевдоним для типа any. А для функций это — $TSFixMeFunction = (…args: any[]) => any;. Рекомендуется избегать использования типа any, но его применение помогло нам упростить процесс миграции. Использование этого типа помогало нам точно узнавать о том, какие именно фрагменты кода нуждаются в доработке.

Стоит отметить, что плагин eslintFixPlugin запускается два раза. Первый раз — до применения tsIgnorePlugin, так как форматирование способно подействовать на сообщения о том, где именно происходят ошибки компиляции. Второй раз — после применения tsIgnorePlugin, так как добавление в код комментариев @ts-ignore может привести к появлению ошибок форматирования.

Дополнительные замечания

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

  • В TypeScript 3.7 появились комментарии @ts-nocheck [50], которые можно добавлять на верхнем уровне TypeScript-файлов для отключения семантических проверок. Мы эти комментарии не использовали, так как раньше они подходили только для .js-файлов, но не для .ts/.tsx-файлов. В современных условиях эти комментарии могут представлять собой отличный вспомогательный механизм, применяемый на промежуточных стадиях миграции.
  • В TypeScript 3.9 появилась поддержка комментариев @ts-expect-error [51]. Если перед строкой кода есть префикс в виде такого комментария, TypeScript не будет сообщать о соответствующей ошибке. Если же в подобной строке ошибки нет, TypeScript сообщит о том, что в комментарии @ts-expect-error необходимости нет. В кодовой базе Airbnb осуществлён переход с комментариев @ts-ignore на комментарии @ts-expect-error.

Итоги

Миграция кодовой базы Airbnb с JavaScript на TypeScript всё ещё продолжается. У нас есть некоторые старые проекты, которые всё ещё представлены JavaScript-кодом. В нашей кодовой базе всё ещё часто встречаются $TSFixMe и комментарии @ts-ignore.

Обзор ts-migrate — инструмента для перевода крупномасштабных проектов на TypeScript - 3

JavaScript и TypeScript в Airbnb

Но нужно отметить, что применение ts-migrate очень сильно ускорило процесс перевода наших проектов с JS на TS и сильно улучшило продуктивность нашего труда. Благодаря ts-migrate программисты смогли сосредоточить усилия на улучшении типизации, а не на ручной обработке каждого файла. В настоящее время примерно 86% нашего фронтенд-монорепозитория, в котором имеется около 6 миллионов строк кода, переведено на TypeScript. Мы, к концу этого года, ожидаем достичь показателя в 95%.

Здесь [52], на главной странице репозитория проекта, вы можете узнать о том, как установить и запустить ts-migrate. Если вы найдёте в ts-migrate какие-то проблемы [53], или если у вас будут идеи по улучшению этого инструмента — приглашаем вас присоединиться [54] к работе над ним!

Доводилось ли вам переводить большие проекты с JavaScript на TypeScript?

Обзор ts-migrate — инструмента для перевода крупномасштабных проектов на TypeScript - 4 [55]

Автор: ru_vds

Источник [56]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/razrabotka/356613

Ссылки в тексте:

[1] здесь: https://www.youtube.com/watch?v=P-J9Eg7hJwE

[2] Image: https://habr.com/ru/company/ruvds/blog/517312/

[3] allowJS: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#--declaration-and---allowjs

[4] codemods: https://medium.com/@cpojer/effective-javascript-codemods-5a6686bb46fb

[5] React: https://reactjs.org/

[6] jscodeshift: https://github.com/facebook/jscodeshift

[7] ts-migrate: https://github.com/airbnb/ts-migrate/tree/master/packages/ts-migrate

[8] ts-migrate-server: https://github.com/airbnb/ts-migrate/tree/master/packages/ts-migrate-server

[9] ts-migrate-plugins: https://github.com/airbnb/ts-migrate/tree/master/packages/ts-migrate-plugins

[10] migration: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate/cli.ts#L99

[11] reignore: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate/cli.ts#L174

[12] TSServer: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-server/src/forkTSServer.ts

[13] используется: https://github.com/Microsoft/vscode/blob/dfafad3a00f02469b644c76613d08716b8b31d8d/extensions/typescript-language-features/src/tsServer/server.ts#L139

[14] языковой протокол: https://microsoft.github.io/language-server-protocol/

[15] Средство для выполнения миграции: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-server/src/migrate/index.ts#L16

[16] Разбор: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-server/src/migrate/index.ts#L19

[17] Создание: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-server/src/migrate/index.ts#L54

[18] Отправка: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-server/src/migrate/index.ts#L103

[19] Обработка: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-server/src/migrate/index.ts#L135

[20] обновляем содержимое: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-server/src/migrate/index.ts#L147

[21] examples: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-example/src/index.ts#L19

[22] main: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate/cli.ts#L96

[23] примеры плагинов: https://github.com/airbnb/ts-migrate/tree/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-example/src

[24] Плагины: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-example/src/example-plugin-jscodeshift.ts

[25] Плагины: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-example/src/example-plugin-ts.ts

[26] Плагины: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-example/src/example-plugin-text.ts

[27] конвейера миграции: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-example/src/index.ts#L18

[28] recast: https://github.com/benjamn/recast

[29] explicitAnyPlugin: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-plugins/src/plugins/explicit-any.ts

[30] declareMissingClassPropertiesPlugin: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-plugins/src/plugins/declare-missing-class-properties.ts

[31] значит: https://github.com/microsoft/TypeScript/blob/20ecbb0f46105ccaead2970f6ef23188955e023e/src/compiler/diagnosticMessages.json#L1348-L1351

[32] ES6-классам: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes

[33] stripTSIgnorePlugin: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-plugins/src/plugins/strip-ts-ignore.ts

[34] hoistClassStaticsPlugin: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-plugins/src/plugins/hoist-class-statics.ts

[35] плагин: https://github.com/airbnb/ts-migrate/tree/master/packages/ts-migrate-plugins/tests/src

[36] ts-migrate: https://github.com/airbnb/ts-migrate/tree/master/packages/ts-migrate-server/tests/commands/migrate

[37] reactPropsPlugin: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-plugins/src/plugins/react-props.ts

[38] этом: https://github.com/lyft/react-javascript-to-typescript-transform

[39] /objectOf$/: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-plugins/src/plugins/utils/react-props.ts#L237

[40] reactDefaultPropsPlugin: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-plugins/src/plugins/react-default-props.ts

[41] defaultProps: https://reactjs.org/docs/typechecking-with-proptypes.html

[42] концепции: https://reactjs.org/docs/state-and-lifecycle.html

[43] reactClassStatePlugin: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-plugins/src/plugins/react-class-state.ts

[44] reactClassLifecycleMethodsPlugin: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-plugins/src/plugins/react-class-lifecycle-methods.ts

[45] React-хуками: https://reactjs.org/docs/hooks-intro.html

[46] Prettier: https://prettier.io/

[47] ESLint: https://eslint.org/

[48] плагином: https://github.com/airbnb/ts-migrate/blob/fe1b6021783b1ef5c4b8fa310b96a44779cc77bd/packages/ts-migrate-plugins/src/plugins/eslint-fix.ts

[49] tsIgnorePlugin: https://github.com/airbnb/ts-migrate/blob/e163ea39a8bd62105773625236f9b4098883c4f3/packages/ts-migrate-plugins/src/plugins/ts-ignore.ts

[50] @ts-nocheck: https://devblogs.microsoft.com/typescript/announcing-typescript-3-7/#ts-nocheck-in-typescript-files

[51] @ts-expect-error: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html#-ts-expect-error-comments

[52] Здесь: https://github.com/airbnb/ts-migrate

[53] проблемы: https://github.com/airbnb/ts-migrate/issues

[54] присоединиться: https://github.com/airbnb/ts-migrate/blob/master/CONTRIBUTING.md

[55] Image: http://ruvds.com/ru-rub?utm_source=habr&utm_medium=perevod&utm_campaign=ts-migrate-a-tool-for-migrating-to-typescript-at-scale

[56] Источник: https://habr.com/ru/post/517312/?utm_source=habrahabr&utm_medium=rss&utm_campaign=517312