如何为JavaScript模块添加d.ts类型定义?
给CommonJS风格的Node.js库添TypeScript类型定义
1. 修正类型定义的导出匹配
你的Message类用CommonJS导出(module.exports = Message),原.d.ts的ES模块导出方式不匹配,得改成对应格式。
如果是要发布的库,修改typings/index.d.ts:
// typings/index.d.ts declare module '你的库名' { // 替换成package.json里的name字段值,比如"messenger-client" import { EventEmitter } from 'events'; export class Message { constructor(client: MessengerClient, message: any); attachments: any[]; body: string; isGroup: boolean; mentions: { [id: string]: string }; messageID: string; senderID: string; threadID: string; isUnread: boolean; type: 'message'; } export class MessengerClient extends EventEmitter { constructor(options?: Record<string, any>); api: any; // 后续可以根据API文档细化这个类型 options: Record<string, any>; user: { name: string } & Record<string, any>; login(appState: any): Promise<void>; // 给EventEmitter扩展事件类型,让on方法能识别参数类型 on(event: 'ready', listener: (client: MessengerClient) => void): this; on(event: 'messageCreate', listener: (message: Message) => void): this; on(event: string, listener: (...args: any[]) => void): this; } }
如果是本地项目自用,不用declare module,直接给JS文件加类型声明:
// typings/index.d.ts import { EventEmitter } from 'events'; export class Message { constructor(client: MessengerClient, message: any); attachments: any[]; body: string; isGroup: boolean; mentions: { [id: string]: string }; messageID: string; senderID: string; threadID: string; isUnread: boolean; type: 'message'; } export class MessengerClient extends EventEmitter { constructor(options?: Record<string, any>); api: any; options: Record<string, any>; user: { name: string } & Record<string, any>; login(appState: any): Promise<void>; on(event: 'ready', listener: (client: MessengerClient) => void): this; on(event: 'messageCreate', listener: (message: Message) => void): this; on(event: string, listener: (...args: any[]) => void): this; } // 给Client.js绑定类型 declare module '../src/client/Client' { export = MessengerClient; } // 给Message.js绑定类型 declare module '../src/structures/Message' { export = Message; }
2. 配置package.json与TypeScript
- 确保
package.json里的types字段指向正确路径:
{ "name": "你的库名", "main": "./index.js", "types": "./typings/index.d.ts" }
- 如果是本地项目,在
tsconfig.json里添加类型文件扫描:
{ "compilerOptions": { "module": "CommonJS", "target": "ES6", "strict": true }, "include": ["src/**/*", "typings/**/*"] }
3. 在主文件中启用类型提示
方案1:改用TypeScript文件(index.ts)
import { MessengerClient, Message } from './typings/index'; // 或直接import你的库名 const appState = require('./appState.json'); const client = new MessengerClient(); client.on('ready', (client) => { console.log(`Logged in as '${client.user.name}'`); }); client.on('messageCreate', (message: Message) => { console.log(message.body); // 现在能自动补全属性 }); client.login(appState);
方案2:保留JavaScript,开启类型检查
在index.js顶部加注释,让VSCode识别类型:
// @ts-check /// <reference path="./typings/index.d.ts" /> const MessengerClient = require("./src/client/Client"); const appState = require('./appState.json'); const client = new MessengerClient(); client.on('ready', (client) => { console.log(`Logged in as '${client.user.name}'`); }); client.on('messageCreate', (message) => { console.log(message.body); // 自动识别message类型 }); client.login(appState);
4. 排查不生效的情况
如果还是没提示,检查这几点:
package.json的types路径是否写错,比如有没有漏写typings/前缀- 类型定义里的属性名和JS文件完全一致(比如JS里是
messageID,d.ts里不能写成messageId) tsconfig.json的include有没有包含typings目录
内容的提问来源于stack exchange,提问作者Ruri
相关产品推荐
相关产品推荐

