У вас есть приложение 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 .

Наконец, ошибок компиляции нет.

Полный пример доступен на GitHub