Search code examples
typescriptdiscorddiscord.js

Discord.js Guide : Property 'commands' does not exist on type 'Client<boolean>' in Typescript


node:v16.11.0 "discord.js": "^13.2.0"

I am setting up an example Discord.js bot.

In this guide, I am to the point of adding this line:

client.commands = new Collection();

Typescript then complains with: Property 'commands' does not exist on type 'Client<boolean>'

This answer seems to be in the same vein as what I want. However I'm still running into some problems. If I add a declare module "discord.js" and declare new typings, it doesn't seem to extend the existing type, it overwrites it. And when when I do, it doesn't know what a Collection is in my custom typings file, since that's custom to the new Discord.js library. I can't help but feel this shouldn't be required in an official guide.

I'm wondering if anyone else has made a typescript Discord bot and found a newer solution to this problem.

Thank you for your time.


Solution

  • -Edit-

    So I had the opportunity of finding my own question in a search and seeing I'd originally answered the question wrong. It turns out that the reason we are getting this error when following the Discord.js guide is because there is no commands property on the Client class at all. It's just a pattern that the guide uses and Typescript calls it out.

    Once I had Typescript set up correctly for my project, adding that commands was going to represent a Collection<any, any> worked fine.

    src/@types/discord.d.ts

    import { Collection } from "discord.js";
    
    declare module "discord.js" {
      export interface Client {
        commands: Collection<any, any>;
      }
    }
    

    tsconfig.json

    {
      "compilerOptions": {
        "typeRoots": ["src/@types", "node_modules/@types"],
        "outDir": "dist"
      },
      "include": ["src"],
      "exclude": ["node_modules"],
      "extends": "@tsconfig/node18/tsconfig.json"
    }
    

    -Old Answer-

    Okay. So I figured it out.

    Create types/common/discord.d.ts

    And don't do what I did and just include this:

    declare module "discord.js" {
      export interface Client {
        commands: Collection<unknown, any>
      }
    }
    

    Make sure this is at the top.

    import { Collection } from "discord.js";
    

    Then it will actually extend the existing one and bring in Collection for the definition instead of replacing it.

    This solution also required "@typescript-eslint/no-explicit-any": "off" to be added to es-lint, thanks to Collection extending Map and taking any value.