Как я переписал нашу кодовую базу на TypeScript за неделю

Как трудно это может быть? 🤔

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

TypeScript - это JavaScript, только с типами.

Но какие бывают типы? Как это можно просто добавить в JavaScript? Типы определяют, какие значения могут быть присвоены объекту, переменной или константе. JavaScript не заботится об этом, поэтому TypeScript «инкапсулирует» ваш код и выдает ошибки компиляции, когда вы назначаете строку переменной, которая определена с числовым типом.

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

Но зачем нам типы?

Вы можете спросить себя: «Но если это только для меня как разработчика, нужно ли мне это?». Ответ, вероятно, будет отрицательным, если вы единственный, кто работает над небольшим проектом. Но в нашем проекте более 10 консультантов работают над одной и той же кодовой базой. Если вы подумаете об этом и натолкнетесь на такую ​​функцию

export function add(a, b) {
  return a + b;
}

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

import { add } from './utils';
function getAndAddValues(a, b) {
  let sumOfValues = add(a,b);
}

Что произойдет, если ваш коллега отправит объект в «getAndAddValues»? Где предупреждение, если вы используете только JavaScript? Это не предупреждение, это ошибка, и она уже запущена в производство.

TypeScript не скомпилирует этот фрагмент кода, если вы наберете код правильно. И тогда вы бы избавили свою команду от ошибки в продакшене.

Итак, как мне переписать свое приложение на TypeScript?

Когда я пишу «переписать», это не нужно начинать с нуля, потому что я сказал, что TypeScript - это JavaScript, только с типами, верно?

Самая трудоемкая задача - переименовать все ваши файлы JavaScript (.js / .jsx) в файлы TypeScript (.ts / .tsx).

App.jsx - ›App.tsx

Если вы сделаете это сразу, то можете столкнуться с ошибками при связывании с Webpack. Потому что вы не определили никаких правил для файлов TypeScript в своем файле «webpack-config.js».

Если вы используете Create React App, вам, возможно, для этого придется удалить приложение. Или перепрограммируйте свое приложение с помощью response-app-rewired.

Я настоятельно рекомендую использовать awesome-typescript-loader, но есть и другие варианты, такие как ts-loader.

Следуйте инструкциям для загрузчика TypeScript по вашему выбору. И все готово. Или вы? Вам понадобится еще один файл в корне вашего проекта. Вам понадобится файл tsconfig.json.

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

{
  "compilerOptions": {
    "module": "commonjs",
    "noImplicitAny": true,
    "removeComments": true,
    "preserveConstEnums": true,
    "outFile": "./dist/index.js",
    "sourceMap": true
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ]
}

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

Итак, вы думаете, что все готово? Не совсем. Вам понадобится машинописный текст. Это так просто, как

npm i typescript -D

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

Итак, вы заставили меня сломать весь проект? Что теперь?

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

npm i @types/react @types/react-dom -D

Префикс «@ types /» устанавливает пакет в папку с именем @types в папке node_module. Он используется TypeScript для проверки типов при импорте и использовании внешних пакетов. Практически все используемые вами пакеты имеют пакет typings с префиксом @types/{package-name}. Некоторые пакеты даже поставляют собственные типы, что неплохо.

Итак, теперь все ваши внешние типы из зависимостей установлены, и вы готовы написать некоторые из ваших внутренних типов.

Давайте идти! Вот почему вы здесь! (Я думаю 🤔)

Начнем с ввода переменных и констант.

// from this
let name = 'Jesper';
// to this
let name: string = 'Jesper';

Вы можете определять переменные или константы как строку, число, логическое значение или любое другое. (Не используйте ни одного, это все равно что сказать, что вы любите мороженое, но вам нравится теплое… А если серьезно, это похоже на то, как будто вы пробуете TypeScript без типов, почему?).

Посмотрим, как вы пишете набор текста для объектов? Легко, вы декларируете свои интерфейсы. Приведем простой человек-пример.

interface IPerson {
  firstName: string;
  lastName: string;
  age: number;
  isCool: boolean;
}
const person1: IPerson = {
  firstName: 'Jesper',
  lastName: 'Førisdahl',
  age: 25,
  isCool: true,
};

Вы определяете ключи, которые будет иметь объект, и тип ожидаемого значения.

Но Джеспер, это все хорошо ... Но как мне использовать TypeScript с React?

Да, я говорю сам с собой от третьего лица. Смирись с этим.

Легкий. Нравится:

import React from 'react';
// Declare types of props
interface IProps {
  text: string;
}
// Declare types of state
interface IState {
  text: string;
}
// Old stateful declaration
export class TypedComponent extends React.Component<IProps, IState> {
  constructor(props: IProps) {
    super(props);
    this.state = {
       text: props.text,
    };
    ...
  }
  
  ...
render(): JSX.Element {
    return (
      <div>
        {this.state.text}
      </div>
    );
  }
}
// New declaration with hooks
export function TypedComponent(props: IProps) {
  const [text, setText] = React.useState(props.text);
return (
    <div>
      {text}
    </div>
  );
}

Наверное, немного сложнее, чем мне просто сказать «легко». Но при старом способе объявления компонентов с классами вам нужно указать типы для свойств и состояния в ‹…› в таком порядке.

Но как насчет необязательных значений в объекте?

Это так же просто, как добавить знак "?" После имени ключа.

interface IProps {
  text: string;
  additionalText?: string;
}

Итак, теперь у вас есть базовая настройка и введение в TypeScript, чувствуете ли вы себя достаточно уверенно, чтобы переписать свой проект?

В нашем проекте мы используем redux с redux-saga, поэтому, если вас интересует статья в этом формате о том, как мы пишем для этого типизацию, 👏 несколько раз в этой статье и прокомментируйте ниже! 😁

🖐
🎤