У вас есть приложение node.js с большим количеством модулей NPM. Это не было проблемой с обычным JavaScript. Основное преимущество TypeScript - это средство проверки статического типа. Чтобы воспользоваться этим, вам нужно будет начать добавлять в свой код аннотации типов, включая код из сторонних модулей npm.
TypeScript использует файлы объявлений, чтобы понять типы и сигнатуры функций модуля. Процесс добавления этих файлов объявлений в ваш проект изменился, поэтому информация, которую вы найдете в Интернете, может описывать устаревший метод.
Начиная с TypeScript 2.2, есть простой способ добавить файл объявления для популярного модуля npm. Все, что вам нужно сделать, это:
npm install --save-dev @types/module // for example: npm install --save lodash npm install --save-dev @types/lodash
npm
создаст node_modules/@types
подкаталоги для каждого модуля с index.d.ts
файлом. Этот файл не содержит кода. Это всего лишь файл, описывающий интерфейс модуля, например классы и типы. Вам все еще нужно импортировать фактический модуль.
А как насчет модулей, у которых нет файлов объявлений?
Неизбежно вы обнаружите, что используете модуль, у которого нет файлов объявлений в npm. Вам нужно будет написать свой собственный, если вы хотите использовать статическую проверку типов.
Я часами пытался решить эту проблему. В документации TypeScript не объясняется, как это сделать, и информация, которую я нашел в Интернете, часто относилась к более старым версиям TypeScript. Я пишу это в надежде, что хотя бы один человек сэкономит часы времени, пытаясь понять, как написать файл декларации для стороннего модуля.
Во-первых, давайте посмотрим на tsconfig.json
. Существует свойство typeRoots
, которое не установлено по умолчанию, но настраивает, где искать файлы объявлений. По умолчанию выполняется поиск node_modules/@types
. Поскольку поиск ведется только внутри node_modules
, это не то место, куда вы можете поместить свои собственные файлы.
Итак, первый шаг - добавить в наш проект новый каталог, в котором мы хотим хранить наши собственные файлы объявлений. В этом примере я буду использовать @types
для этого каталога, но вы можете назвать его как хотите.
tsconfig.json { "compilerOptions": { "outDir": "./built", "allowJs": true, "noImplicitAny": true, "strictNullChecks": true, "target": "es6", "module": "commonjs" }, "include": [ "./src/**/*" ], "exclude": [ "node_modules" ] }
Этот файл конфигурации включает noImplicitAny
, что означает, что вы должны явно добавить аннотации типов. Вы должны отключить это, если у вас есть большой проект, который вы хотите перенести со временем.
Он также добавляет ̶t̶y̶p̶e̶R̶o̶o̶t̶s̶: ̶ ̶ [̶»̶ @ ТИПЫ» ̶, ̶ ̶»̶.̶/̶@̶t̶y̶p̶e̶s̶» ̶] ̶. Это говорит машинописи компилятор для Ищу ̶.̶d̶.̶t̶s̶ ФАЙЛЫ в ОБА ̶n̶o̶d̶e̶_̶m̶o̶d̶u̶l̶e̶s̶ / ̶ @ ̶t̶y̶p̶e̶s̶ ̶a̶s̶ ̶w̶e̶l̶l̶ ̶a̶s̶ ̶o̶u̶r̶ ̶c̶u̶s̶t̶o̶m̶ ̶d̶i̶r̶e̶c̶t̶o̶r̶y̶ ̶.
ОБНОВЛЕНИЕ (2018–02–01): Как указано в комментариях, в последних версиях TypeScript больше нет необходимости указывать typeRoots
в tsconfig.json
.
Теперь мы можем создать наш файл пользовательской декларации. В этом примере я покажу, как написать файл объявления для модуля npm dir-obj
, потому что это проблема, которую я пытался решить.
Начнем с создания нового проекта
mkdir ~/dev/myproject cd ~/dev/myproject mkdir src mkdir built vim tsconfig.json # Add outDir, include, and set noImplicitAny <paste> { "compilerOptions": { "outDir": "./built", "module": "commonjs", "target": "es6", "noImplicitAny": true, "sourceMap": false }, "include": [ "src/**/*" ] } </paste> vim src/index.ts <paste> import * as dirObj from 'dir-obj'; const project = dirObj.readDirectory(__dirname + '/..', { fileTransform: (file: dirObj.File) => { return file.fullpath; } }); console.log(JSON.stringify(project, null, 2)); </paste>
Этот простой файл будет читать структуру каталогов проекта и выводить полный путь к каждому файлу.
Чтобы скомпилировать файл TypeScript в файл JavaScript ES5, из корня проекта выполните:
tsc -p .
-p
указывает tsc
искать tsconfig.json
файл в текущем каталоге.
Предупреждение! Не удалось найти файл декларации для модуля
src/index.ts(1,25): error TS7016: Could not find a declaration file for module 'dir-obj'. '/Users/chris/dev/personal/typescript-examples/node_modules/dir-obj/index.js' implicitly has an 'any' type.
В текущей настройке tsc
не может проверять статическим типом правильность нашего кода. Для этого нам нужно добавить файл декларации.
mkdir src/@types mkdir src/@types/dir-obj vim src/@types/dir-obj/index.d.ts
Здесь мы создали наш собственный каталог @types
в каталоге src
, чтобы файлы автоматически включались во время компиляции.
Мы добавим файл декларации для модуля dir-obj
. Ваши файлы объявлений должны находиться в каталоге, который соответствует имени модулей npm.
Создайте файл декларации
/// <reference types="node" /> declare module 'dir-obj' { import { Stats } from "fs"; export interface readOptions { filter?: RegExp | Filter, dirTransform?: DirTransform, fileTransform?: FileTransform } export type Filter = (file: File) => boolean; export type DirTransform = (file: File, value: any) => any; export type FileTransform = (file: File) => any; export function readDirectory(dir: string, options?: readOptions): object; export class File { key: string; readonly path: string; readonly fullpath: string; readonly ext: string; readonly name: string; readonly basename: string; constructor(dir: string, file: string); readonly attributes: Stats; readonly isDirectory: boolean; readonly isRequirable: boolean; } }
Мы начинаем файл объявления с declare module 'dir-obj'
, чтобы явно указать модуль, который мы документируем.
Остальная часть файла объявления - это список функций и классов, доступных в исходном коде JavaScript, но с добавленной информацией о типе. Выяснение того, как смотреть на исходный код JavaScript и выяснение того, как написать определение типа для этого, выходит за рамки этой статьи, но, надеюсь, это поможет вам встать на путь.
Скомпилируйте проект
tsc -p .
Наконец, ошибок компиляции нет.