TypeScript
Leverage TypeScript for better type safety and development experience.
Robo.js has first-class TypeScript support. There is no need to configure compilation or set up build pipelines manually. The dev and build commands handle everything, using the Rust-based SWC compiler for fast builds.
Setting Up TypeScript Projects
The create-robo CLI can scaffold a TypeScript project directly:
npx create-robo@next my-awesome-robo --tsFor existing projects, install @swc/core and typescript as dev dependencies, create a tsconfig.json file, and rename your .js files to .ts:
npm install --save-dev @swc/core typescriptExample tsconfig.json:
{
"compilerOptions": {
"target": "ESNext",
"lib": ["esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"incremental": true
},
"include": ["**/*.ts"],
"exclude": ["node_modules"]
}TypeScript Types in Robo.js
Robo.js ships with native TypeScript types. Common types include Config, Plugin, and Manifest. Platform-specific types like CommandConfig and EventConfig are provided by their respective plugins (e.g., @robojs/discordjs).
Example of a typed async command:
import { createCommandConfig } from '@robojs/discordjs'
export const config = createCommandConfig({
description: 'An async example command'
})
export default async () => {
await new Promise((resolve) => setTimeout(resolve, 1000))
return 'Waited for 1 second.'
}import { createCommandConfig } from '@robojs/discordjs'
export const config = createCommandConfig({
description: 'An async example command'
})
export default async () => {
await new Promise((resolve) => setTimeout(resolve, 1000))
return 'Waited for 1 second.'
}For interaction types, import directly from Discord.js:
import { CommandInteraction } from 'discord.js'
export default (interaction: CommandInteraction) => {
interaction.reply('Hello, TypeScript!')
}export default (interaction) => {
interaction.reply('Hello, TypeScript!')
}Building Plugins with TypeScript
Plugins can be built with TypeScript for better type safety. The robo build plugin command handles compilation:
npx robo build pluginTypeScript in Config Files
Config files use JavaScript format, but TypeScript's @type annotation comments provide type checking and autocompletion in editors like VS Code:
// config/robo.mjs
// @ts-check
/** @type {import('robo.js').Plugin} */
const gptPlugin = [
'@robojs/ai',
{
// Plugin config options
}
]
/** @type {import('robo.js').Config} */
export default {
plugins: [gptPlugin]
}The @ts-check and @type annotations enable autocompletion and type checking in supported editors without requiring the config file itself to be TypeScript.
Path Aliases
Path aliases simplify deep imports by replacing long relative paths with short, readable prefixes.
Add aliases to your tsconfig.json:
{
"compilerOptions": {
"paths": {
"@/robo/*": ["src/*"],
"@/something/*": ["src/modules/something/*"]
}
}
}TypeScript resolves @/robo/ to src/ and @/something/ to src/modules/something/. The baseUrl defaults to the project root.
Before and after:
// Before
import { someVariable } from '../../../../modules/something/commands/someCommand.js'
// After
import { someVariable } from '@/something/commands/someCommand.js'// Before
import { someVariable } from '../../../../modules/something/commands/someCommand.js'
// After
import { someVariable } from '@/something/commands/someCommand.js'Monorepos
Monorepos bundle multiple projects in a single repository, making code sharing straightforward. Robo.js works naturally in monorepo setups.
A typical layout:
Use path aliases to import from other packages:
{
"compilerOptions": {
"paths": {
"@/api/*": ["../api/dist/*"],
"@/robo/*": ["src/*"],
"@/something/*": ["src/modules/something/*"]
}
}
}Note: Always reference compiled files (in /dist), not raw .ts sources, when sharing code across TypeScript projects in a monorepo.
With this configuration, importing from another package works as expected:
import { someFunction } from '@/api/someFile.js'import { someFunction } from '@/api/someFile.js'