Практическое руководство по использованию TypeScript для разработчиков JavaScript.
В этой серии статей предполагается, что читатель имеет разумное понимание JavaScript ES2015 (Learn ES2015) и минимальное понимание TypeScript (TypeScript за 5 минут).
Если вы заинтересованы в том, чтобы продолжить, мы бы порекомендовали вам сформировать проект, используя упрощенную настройку в разделе Backend статьи Tech Stack 2019: Core и используйте Visual Studio Code с расширением TSLint в качестве редактора.
Есть две крайние точки зрения на переход от JavaScript к TypeScript.
Сначала "что это, черт возьми?"
Другой - «в чем дело?»
Более точная перспектива - это зависит от сделанного выбора.
Первый пример взят из Ts.ED (TypeScript Framework поверх Express), в котором используются декораторы:
С появлением классов в TypeScript и ES6 теперь существуют определенные сценарии, требующие дополнительных функций для поддержки аннотирования или изменения классов и членов классов. Декораторы позволяют добавлять аннотации и синтаксис метапрограммирования для объявлений классов и членов. Декораторы представляют собой предложение этапа 2 для JavaScript и доступны в качестве экспериментальной функции TypeScript.
- TypeScript - Декораторы
С другой стороны, можно писать приложения TypeScript Express, которые практически не отличаются от своих эквивалентов на JavaScript; например, нам нужно изменить только одну строку (import против require) в Express Hello World Example .
В то же время, даже если кто-то выберет более традиционный подход JavaScript (наш подход в этой статье и мои общие предпочтения), есть несколько важных TypeScript концепции, не описанные в TypeScript за 5 минут, которые необходимо знать.
примечание: в качестве примечания: официальный TypeScript Handbook написан очень хорошо (множество примеров и т. д.); в то же время трудно отличить часто встречающиеся концепции от более тонких крайних случаев.
Вывод типа
В TypeScript есть несколько мест, где вывод типа используется для предоставления информации о типе, когда нет явной аннотации типа.
- TypeScript - Вывод типа
Если вы использовали другие типизированные языки, например Java, вы, возможно, были бы удивлены, увидев следующий код:
... const port = 3000; ...
примечание: в этих примерах я снова вставляю точки с запятой; мне все еще кажется странным без них.
В этом случае компилятор TypeScript может сделать вывод, что порт - это номер, поскольку он назначен номеру ( 3000).
Можно было явно (но с избыточностью) ввести порт с помощью:
... const port: number = 3000; ...
С другой стороны, необходимо явно указать переменные, когда они объявлены без присваивания:
... let port: number; port = 3000; ...
Другой пример вывода типа (контекстная типизация) скрыт в строке ниже:
... app.get('/', (req, res) => res.send('Hello World!')) ...
В нашем редакторе мы видим, что res типа Response:
В этом случае компилятор TypeScript может вывести базу сигнатуры типа функции на основе своего контекста, в данном случае в качестве второго параметра функции get.
С другой стороны, мы должны явно ввести параметры функции, когда они объявлены вне контекста:
import express, { Request, Response } from 'express'; ... const handleGet = (req: Request, res: Response) => res.send('Hello World'); app.get('/', handleGet); ...
Файлы декларации
Предыдущий пример освещает одну из самых больших проблем с использованием TypeScript; отсутствие документации по типам для сторонних библиотек. Хотя это очевидно, если взглянуть на это, как мы узнали, что нужно импортировать типы Request и Response из express?
Официальная ссылка Express на Response не упоминает типы TypeScript. Фактически, библиотека Express не предоставляет собственные определения типов, а скорее зависит от библиотеки @ types / express (экспортированной из ОпределенноTyped ).
Важно отметить, что сторонние библиотеки, например, Express, поставляются как JavaScript; , поэтому нам нужно потреблять файлы объявления типа, чтобы использовать их с TypeScript. Эти файлы объявления типа могут поставляться в том же пакете, что и JavaScript, или в отдельном пакете (как в случае Express).
Давайте рассмотрим типичный сценарий использования сторонней библиотеки (скажем, в новом проекте TypeScript); в данном случае Express.
Начнем с установки библиотеки в соответствии с ее документацией, например, в Express документации :
npm install express
Мы используем их документацию для использования библиотеки (пример привет мир; замена require на import) и сразу получаем ошибку компилятора TypeScript:
К счастью, ошибка подсказывает нам решение:
npm install @types/express
После установки этой дополнительной библиотеки ошибки устранены.
Хотя пример Express hello world построен так, что можно вывести все типы, в конечном итоге, вероятно, захочется использовать явную типизацию, например,
... const handleGet = (req: Request, res: Response) => res.send('Hello World'); ...
Один из приемов определения набора текста (скажем, типа Response) заключается в том, чтобы наблюдать за предполагаемым набором текста (при наведении курсора на параметры в редакторе) в исходном коде и угадывать типы, которые необходимо импортировать (9 раз из 10 это работает для меня).
Однако в зависимости от того, над чем навести курсор мыши, можно прийти к другому решению. Например, при наведении курсора на метод get мы видим, что второй параметр get - это RequestHandler (или их массив); с использованием параметров отдыха.
Используя RequestHandler, мы получаем более явное (и, следовательно, лучшее) определение handleGet.
import express, { RequestHandler } from 'express'; ... const handleGet: RequestHandler = (req, res) => res.send('Hello World'); app.get('/', handleGet); ...
примечание: признание… До написания этой статьи я привык использовать менее явную реализацию с использованием интерфейсов Request и Response.
Более удовлетворительный ответ (вместо предположения об импорте) состоит в том, что можно проверить файл определения типа; ./node_modules/@types/express/index.d.ts. Затем мы видим, что он экспортирует RequestHandler.
... interface RequestHandler extends core.RequestHandler { } ...
который расширяет RequestHandler, экспортированный в ./node_modules/@types/express-serve-static-core/index.d.ts.
... export interface RequestHandler { ... (req: Request, res: Response, next: NextFunction): any; } ...
Дальнейшие действия
Мы продолжим изучение часто используемых, но менее очевидных концепций TypeScript в TypeScript: The Hard (er) Parts: Part 2.