Типизация функции на чистом JavaScript через JSDoc, чтобы её проверял tsc
Файл .js в проекте, где включены allowJs и checkJs. Сейчас компилятор выводит any для обоих параметров, поэтому неверная точка вызова вообще не сообщается.
Требования: описать форму объекта user один раз как переиспользуемый именованный тип, аннотировать оба параметра и возвращаемое значение, и сделать это без переименования файла в .ts и без импортов.
// @ts-check
function formatUser(user, upper) {
return upper ? user.name.toUpperCase() : user.name;
}
formatUser({ name: 42 }, 'yes'); // должно стать ошибкой
Допишите реализацию.
Описать форму один раз через @typedef, затем аннотировать функцию тегами @param {Type} name и @returns. Под @ts-check компилятор читает эти теги как настоящие типы, поэтому formatUser({ name: 42 }, 'yes') не соберётся — без переименования файла.
- ✗Думать, что теги JSDoc — только документация и не могут проверить типы в
.js-файле - ✗Писать синтаксис аннотаций TypeScript внутри
.js-файла, что является ошибкой разбора - ✗Забыть
@ts-checkилиcheckJs, из-за чего теги разобраны, но ничего не проверяется
- →Как выразить обобщённую функцию в JSDoc, и какой тег для этого нужен?
- →Что может выразить
.ts-файл из того, что не может JSDoc внутри.js?
Решение
@typedef объявляет форму один раз, @param и @returns навешивают типы на сигнатуру. Никакого переименования и нового шага сборки — файл остаётся .js.
// @ts-check
/**
* @typedef {object} User
* @property {string} name
*/
/**
* @param {User} user
* @param {boolean} upper
* @returns {string}
*/
function formatUser(user, upper) {
return upper ? user.name.toUpperCase() : user.name;
}
formatUser({ name: 42 }, 'yes');
// ❌ Type 'number' is not assignable to type 'string'
// ❌ Argument of type 'string' is not assignable to parameter of type 'boolean'
Почему это работает
@ts-check включает для этого .js-файла тот же самый проверяющий, что работает по .ts. Он читает теги JSDoc как настоящие аннотации: User становится обычным типом, а не подсказкой редактора, и обе ошибки в вызове — ошибки сборки, а не только красные подчёркивания.
⚠️ Синтаксис аннотаций TypeScript (user: User) в .js писать нельзя — это ошибка разбора. Всё выражается тегами, и в этом же главный минус подхода.