typescript - ¿Cómo aumentar un módulo JS para agregar una nueva interfaz?
Tengo un proyecto de TypeScript NodeJS con allowJS, y uno de mis archivos JavaScript CommonJS contiene una clase Logger. Me gustaría ampliar el archivo JS con una declaración de interfaz ILogger, para que pueda import {Logger, ILogger} from './logger'; en archivos TypeScript.
Según la respuesta a Usar interfaz definida en JSDoc en TypeScript, TypeScript no soporta JSDoc @interface, por lo que debería usar un archivo de declaración .d.ts en su lugar. Pero no puedo averiguar cómo combinar un archivo JS que contiene una clase con un archivo de declaración que contiene una interfaz de manera que ambos puedan ser importados desde un archivo TypeScript.
Intento 1: Tanto logger.js como logger.d.js: TypeScript solo lee tipos de logger.d.ts
Poner la clase en un archivo js y la interfaz en un archivo d.ts con el mismo nombre excluyendo la extensión no funciona, porque TypeScript solo lee los tipos del archivo d.ts e ignora la clase en el archivo JS:
Error: app.ts:1:18 - error TS2724: '"./logger"' no tiene un miembro exportado llamado 'Logger'. ¿Quiso decir 'ILogger'?
// logger.js
//@ts-check
exports.Logger = class Logger {
/**
* @param {string} msg
* @returns {void}
*/
info(msg) {
console.log(msg);
}
}
// logger.d.ts
export interface ILogger {
info(msg: string): void
}
// app.js
import {ILogger, Logger} from './logger';
export function f(logger: ILogger) {
logger.info('f');
}
export function main() {
const logger = new Logger();
f(logger);
}
// tsconfig.json
{
"extends": "@tsconfig/recommended/tsconfig.json",
"compilerOptions": {
"allowJs": true
}
}
// package.json
{
"devDependencies": {
"@tsconfig/recommended": "^1.0.1",
"typescript": "^4.4.3"
}
}
Intento 2: Ampliando un módulo en un archivo .d.ts referenciado por <reference path=…/>: TypeScript solo lee tipos de logger.js
Cuando intento la ampliación de módulo (declare module '…') del módulo JS ./logger con un archivo de declaración referenciado en una directiva de triple barra (<reference path="…"/>), la ampliación no parece funcionar y TypeScript solo lee la clase del archivo JS e ignora el declare module:
app.ts:2:9 - error TS2724: '"./logger"' no tiene un miembro exportado llamado 'ILogger'. ¿Quiso decir 'Logger'?
TypeScript no da ningún error por una declaración global que agregué, así que sé que está leyendo el archivo types.d.ts.
// logger.js, tsconfig.json, package.json: same as in Attempt 1
// types.d.ts:
declare module './logger' {
export interface ILogger {
info(msg: string): void
}
}
declare function myGlobalFunc(): void
// app.ts:
/// <reference path="./types.d.ts"/>
import {ILogger, Logger} from './logger';
export function f(logger: ILogger) {
logger.info('f');
}
export function main() {
const logger = new Logger();
myGlobalFunc();
f(logger);
}
Intento 3: Aumentar el módulo logger.js en app.ts funciona pero no es limpiamente reutilizable
Cuando intento la ampliación de módulo (declare module '…') del módulo JS ./logger con una declaración en un módulo TypeScript, funciona sin ningún error de TypeScript. Supongo que el único problema es que tengo que duplicar esta extensión de módulo o importar el módulo TypeScript que hace la extensión cada vez que quiero usar la extensión.
// logger.js, tsconfig.json, package.json: same as in Attempt 1
// app.js
import {ILogger, Logger} from './logger';
declare module './logger' {
export interface ILogger {
info(msg: string): void
}
}
export function f(logger: ILogger) {
logger.info('f');
}
export function main() {
const logger = new Logger();
f(logger);
}
¿Hay una mejor manera de agregar una declaración de interfaz de TypeScript a un módulo CommonJS de JavaScript?