Node.js 和 Typescript,如何动态访问导入的模块
Posted
技术标签:
【中文标题】Node.js 和 Typescript,如何动态访问导入的模块【英文标题】:Node.js and Typescript, how to dynamically access imported modules 【发布时间】:2020-07-21 15:39:06 【问题描述】:我正在努力在 TypeScript 中创建一个不和谐的机器人。我想创建一个通用的命令调度程序,这是我到目前为止的工作:
app.ts:
import * as Discord from 'discord.js';
import * as config from '../config'
import * as commands from './Commands/index'
const token : string = config.Token;
const _client = new Discord.Client();
_client.on('message', (msg) =>
let args : Array<string> = msg.content.split(' ')
let command : string = args.shift() || " ";
if(!command.startsWith("!")) return;
else
commands[`$command.toLower().substring(1)`]
)
命令/索引.ts
export default as ping from './ping';
export default as prong from './prong';
Ping.ts:所有命令的结构相同
import Message from "discord.js";
export default
name : 'ping',
description: 'Ping!',
execute(message: Message, args: Array<string>)
message.channel.send('Pong.');
在索引命令导入时,我可以使用以下命令成功调用正确的执行函数:
commands['pong'].execute()
但是,当尝试像这样动态索引它时:
commands[command].execute()
我收到以下错误:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'typeof import("c:/Users/alexs/Desktop/Discord Bot/src/Commands/index")'. No index signature with a parameter of type 'string' was found on type 'typeof import("c:/Users/alexs/Desktop/Discord Bot/src/Commands/index")'
无论如何我可以将命令导入类型转换为某种对象或集合吗?如果没有,有没有办法我可以创建某种访问器来完成这项工作?我是打字稿的新手,很好奇有什么可能。
【问题讨论】:
你怎么打电话给commands[command].execute()
? command
变量从何而来?
【参考方案1】:
我为您的命令建议一种不同的方法,这种方法可以解决两件事:
别忘了正确导出文件 您会收到类型安全的命令让我们首先为你的命令创建一个接口,这个接口描述元数据,你想添加多少就添加多少
export interface Command
name: string
description: string
// Making `args` optional
execute(message: Message, args?: string[]) => any
现在您已经为命令设置了形状,让我们确保您的所有命令都具有正确的形状
import Command from "./types"
// This will complain if you don't provide the right types for each property
const command: Command =
name: "ping",
description: "Ping!",
execute(message: Message, args: string[]) =>
message.channel.send("Pong")
export = command
下一部分是加载你的命令,discord.js 有 glob 作为依赖项,它可以帮助你轻松读取目录中的文件,让我们使用一些实用程序,这样我们就可以很好地使用 async / await
import glob from "glob" // included by discord.js
import promisify from "util" // Included by default
import Command from "./types"
// Make `glob` return a promise
const globPromise = promisify(glob)
const commands: Command = []
client.once("ready", async () =>
// Load all javascript / TypeScript files so it works properly after compiling
// Replace `test` with "await globPromise(`$__dirname/commands/*..js,.ts`)"
// I just did this to fix SO's syntax highlighting!
const commandFiles = test
for (const file of commandFiles)
// I am not sure if this works, you could go for require(file) as well
const command = await import(file) as Command
commands.push(command)
)
const prefix = "!"
client.on("message", message =>
// Prevent the bot from replying to itself or other bots
if (message.author.bot)
return
const [commandName, ...args] = message.content
.slice(prefix.length)
.split(/ +/)
const command = commands.find(c => c.name === commandName)
if (command)
command.execute(message, args)
)
我希望这能给你一个好的起点,并向你展示 TypeScript 的力量
【讨论】:
【参考方案2】:你可以导入类型,然后像这样进行转换
commands[command as Type].execute();
【讨论】:
以上是关于Node.js 和 Typescript,如何动态访问导入的模块的主要内容,如果未能解决你的问题,请参考以下文章
我可以在 Node.js/Express 中动态导入 TypeScript 模块吗?
如何清理 Node.js 和 Typescript 中的响应正文
如何删除多行 typeorm - postgresql 和 node.js(typescript)
如何让 TypeScript 以生成工作 Node.JS 代码的方式加载 PDF.js NPM 模块和 @types 绑定?