#Creating a class

59 messages · Page 1 of 1 (latest)

wide finch
#

Hello, as the title says I am creating a class, this class it for an events. I've came up with the following class, I am trying to inherit parameters from and interface given the enum value.```ts
import { ClientEvents, Events } from 'discord.js'

import client from './client'

type EventName = keyof ClientEvents

export default class Event {
name: Events
run: (client: client, ...event: ClientEvents[EventName] | any) => Promise<void>
}

This doesn't quite give the results I am looking for, I'm not even sure what I am trying to achieve is possible. I will provide an example of what the interface looks like below:
#
export interface ClientEvents {
  applicationCommandPermissionsUpdate: [data: ApplicationCommandPermissionsUpdateData];
  autoModerationActionExecution: [autoModerationActionExecution: AutoModerationActionExecution];
  autoModerationRuleCreate: [autoModerationRule: AutoModerationRule];
  autoModerationRuleDelete: [autoModerationRule: AutoModerationRule];
  autoModerationRuleUpdate: [
    oldAutoModerationRule: AutoModerationRule | null,
    newAutoModerationRule: AutoModerationRule,
  ];
  cacheSweep: [message: string];
  channelCreate: [channel: NonThreadGuildBasedChannel];
  channelDelete: [channel: DMChannel | NonThreadGuildBasedChannel];
  channelPinsUpdate: [channel: TextBasedChannel, date: Date];
  channelUpdate: [
    oldChannel: DMChannel | NonThreadGuildBasedChannel,
    newChannel: DMChannel | NonThreadGuildBasedChannel,
  ];
...
}
#

I want to be able to use the class like:```ts
import { Events } from 'discord.js'

import Logger from '../helpers/logger'
import Event from '../structure/event'
import client from '../structure/client'

export default new Event(Events.ClientReady, async (client: client) => {
if (client.user === null) return
Logger('cyan', [+] ${client.user?.tag} is ready!, true)
})

reef condorBOT
#
Ascor8522#7606

Preview:```ts
import {Client, ClientEvents, Events} from "discord.js"

// import client from './client';
declare const client: Client
declare function Logger(...params: any[]): void

export class Event<T extends keyof ClientEvents> {
public name: T
public run: (
client: Client,
...event: ClientEvents[T]
) => void

pu
...```

echo willow
#

not too sure about the events tho

proud bluff
#

the generic above works

echo willow
#

since addListener uses (...args: any[]) => void for the listeners

proud bluff
#

that's the general pattern used

echo willow
#

which is not compatible with (client: Client, ...event: ClientEvents[T]) => void

#

the client is a simple event emitter

proud bluff
#

djs has an override for on

echo willow
#

so either discord.js doesn't provide the right types, or I'm missing something

#

oh

#

was using addListener

proud bluff
#

addListener isn't really used. idk if it's overridden

echo willow
#

then

reef condorBOT
#
Ascor8522#7606

Preview:```ts
import {Client, ClientEvents, Events} from "discord.js"

// import client from './client';
declare const client: Client
declare function Logger(...params: any[]): void

export class Event<T extends keyof ClientEvents> {
public name: T
public run: (
client: Client,
...event: ClientEvents[T]
) => void
...```

echo willow
#

tbh I don't really see the point of creating a class and an instance just for an event listener, but ok

#

@wide finch

proud bluff
wide finch
#

This indeed help alot, although I am using an extended client in order to attach custom properties

#

Trying to include the client.on(this.name, (...args: ClientEvents[T]) => this.run(client, ...args)); inside of the importing of events```ts
async importEvents (): Promise<void> {
const events = readdirSync('./dist/events/')

events.map(async (file) => {
  await import(join(__dirname, '../events/', file)).then((file) => {
    const event = file.default as typeof Event | undefined

    if (event === undefined) return
                                             //     errors
                                            // V                V
    this.on(event.name, (...args: ClientEvents[T]) => { event.run(client, ...args) })
    Logger('cyan', `[+] ${event.name.toString()} event loaded.`, true)
  }).catch((err) => {
    Logger('red', `[-] ${file} couldn't be loaded.`, true)
    console.error(err)
  })
})

}

proud bluff
#

don't type args, it'll be taken from the overload that already exists

wide finch
#

Oh alright so I fixed that and changed it to this.on(event.name, (...args) => { event.run(this, ...args) })

#

still receiving this message Property 'run' does not exist on type 'typeof Event'. ts(2339)

proud bluff
#

oh, you're using typeof Event rather than Event

#

was wondering where that was coming from

#

typeof Event refers to the class itself, you need Event, an instance of the class

#

also you could use if (!event) btw

wide finch
#

we encountered a new issue when removing typeof

#

This assertion is unnecessary since it does not change the type of the expression. eslint @ typescript-eslint/no-unnecessary-type-assertion
Generic type 'Event<T>' requires 1 type argument(s).ts(2314)

proud bluff
#

Event<keyof ClientEvents>

#

or you can have keyof ClientEvents as a default for the generic in the class itself as well

#

the eslint thing is just because it can't resolve Event

wide finch
#

Oh okay yeah that makes sense

#

Also I know he passed the discord client through the event class

#

but should I used my extend class for that or just leave it as it is?

proud bluff
#

"he"...?

#

that's up to you, you could absolutely say that you use your own client as the argument

wide finch
#

he as in Ascor

#

When using my client as an argument I get the following messages:

No overload matches this call.
  Overload 1 of 2, '(eventEmitter: import("d:/discord bots/hawk-bot/node_modules/@types/node/events.d.ts"), eventName: string): AsyncIterableIterator<any>', gave the following error.
    Argument of type 'string' is not assignable to parameter of type 'import("d:/discord bots/hawk-bot/node_modules/@types/node/events.d.ts")'.
      Type 'string' is not assignable to type 'import("d:/discord bots/hawk-bot/node_modules/@types/node/events.d.ts")'.
  Overload 2 of 2, '(emitter: EventEmitter, eventName: string, options?: StaticEventEmitterOptions | undefined): AsyncIterableIterator<any>', gave the following error.
    Argument of type 'string' is not assignable to parameter of type 'EventEmitter'.
      Type 'string' is not assignable to type 'EventEmitter'.ts(2769)

###################################

Argument of type 'typeof client' is not assignable to parameter of type 'client'.
  Type 'typeof client' is missing the following properties from type 'client': commands, slashs, importCommands, importEvents, and 48 more.ts(2345)
event.ts(12, 67): Did you mean to use 'new' with this expression?
proud bluff
#

can you show your current code for both the listener and Event

wide finch
#

So I moved the listener into my client seems to solve the issue I was having, only have an issue with my command class now. But I am pretty sure I am able to resolve that issue.

Event: ```ts
import { type ClientEvents } from 'discord.js'

import type client from './client'

export default class Event<T extends keyof ClientEvents> {
public name: T
public run: (client: client, ...event: ClientEvents[T]) => void

public constructor (name: Event<T>['name'], run: Event<T>['run']) {
this.name = name
this.run = run
}
}

Listener:```ts
async importEvents (): Promise<void> {
    const events = readdirSync('./dist/events/')

    events.map(async (file) => {
      await import(join(__dirname, '../events/', file)).then((file) => {
        const event = file.default as Event<keyof ClientEvents> | undefined

        if (event == null) return

        this.on(event.name, (...args) => { event.run(this, ...args) })
        Logger('cyan', `[+] ${event.name} event loaded.`, true)
      }).catch((err) => {
        Logger('red', `[-] ${file} couldn't be loaded.`, true)
        console.error(err)
      })
    })
  }
proud bluff
#

you can use parameter properties to clean up your Event btw

#

!hb parameter properties

reef condorBOT
wide finch
#

so it doesn't need the constructor?

#

or wait nvm you mean using as event.foo

proud bluff
#

what?

wide finch
#

By parameter properties you mean event.name for an example?

proud bluff
#

no, those are just the class properties

#

check the handbook link

wide finch
#

public, private, protected, and readonly

proud bluff
#

those are modifiers

#

uh, try reading the description

wide finch
#

Also shows that I can do this, which I am pretty sure that is what you mean by clean up?```ts
export default class Event<T extends keyof ClientEvents> {
public constructor (
public name: T,
public run: (client: client, ...event: ClientEvents[T]) => void | Promise<void>
) { }
}

proud bluff
#

yeah

wide finch
#

Thank you for all the help, I really appreciate it