1 year ago
#327294
DeMineArchiver
TypeError: "method is not a function" error when downcasting to a subclass - discrord.js
Please, don't mind my grammar and code mistakes because I am a self-taught coder
I am developing a multi-purpose Discord bot with NodeJS using discord.js and typescript libraries.
When creating the ticket system, and trying to make it as universal as possible, I ran into a problem with downcasting subclasses. To create a ticket text channel, I use CategoryChannel.createChannel()
method, which returns Promise<GuildChannel>
, in my case, I set the CategoryCreateChannelOptions.type
to "GUILD_TEXT"
, so the method returns Promise<TextChannel>
.
After creating a channel, I want to add custom properties to it, such as tickedID: string
(a custom random UID I generate for each ticket), ticketGroup: string
(a group which the ticket belongs to, in order to differentiate between tickets from different categories, for example: support, suggestion, warning, form ticket categories) and channelID: string
(ID of the channel the ticket is).
To do that, I have created a Ticket
class, which extends TextChannel
.
Here's a cleanified version of the Ticket
class code:
// Imports
import { Guild, Message, MessageOptions, TextChannel } from "discord.js";
import { RawGuildChannelData } from "discord.js/typings/rawDataTypes";
import { TicketSetupFunctionOptions, TicketType } from "../Types/Ticket";
import { BetterClient } from "./Client";
// Ticket class
export class Ticket extends TextChannel implements TicketType{
public ticketID: string;
public ticketGroup: string;
public channelContent: MessageOptions[];
public constructor(options: TicketType, guild: Guild, data?: RawGuildChannelData, client?: BetterClient, immediatePatch?: boolean) {
super(guild, data, client, immediatePatch);
Object.assign(this, options);
}
// Setup method, the one which is the main problem
public async setup<TicketSetupFunction>(options: TicketSetupFunctionOptions): Promise<Ticket> {
// Do the code (it have never got to point of executing the code so there's no reason to put it here)
return new Promise<Ticket>((resolve, reject) => {
resolve(this);
});
}
}
I even tried putting the setup()
method into the type, but it didn't help. Type TicketType
:
// Imports
import { MessageOptions, TextChannel } from "discord.js";
import { Ticket } from "../Structures/Ticket";
// Types
export interface TicketSetupFunctionOptions {
channelContent: MessageOptions[];
}
export type TicketSetupFunction = (TicketSetupFunctionOptions) => Promise<Ticket>;
export type TicketType = {
ticketID: string;
ticketGroup: string;
channelContent?: MessageOptions[];
setup: TicketSetupFunction;
} & TextChannel;
In my TicketManager
class (it is basically the tickets system) I have a TicketManager.createTicket()
method, which takes a CategoryChannelResolvable
and OverwriteResolvable[]
as its arguments, which are then used in CategoryChannel.createChannel()
method. It returns Promise<TextChannel>
, but I need downcast that into returning Ticket
if the promise resolves. Here's the TicketManager.createChannel()
code:
public async createChannel(category: CategoryChannel, permissions: OverwriteResolvable[]): Promise<Ticket> {
const channel = await category.createChannel("ticket-name", {
type: "GUILD_TEXT",
permissionOverwrites: permissions
}) as Ticket;
return new Promise<Ticket>((resolve, reject) => resolve(channel));
}
TicketManager.createTicket()
is used to create, setup and save a ticket to the database. Inside of this method I resolve the category and generate a UID for the ticket.
After that, I call TicketManager.createChannel()
and do the following:
public async createTicket(categoryChannel: CategoryChannelResolvable): Promise<Ticket> {
const ticketID = generateUID(16);
const category = await this.client.guilds.resolve(this.guild).channels.resolve(categoryChannel) as CategoryChannel;
const ticket: Ticket = await this.createChannel(category);
await ticket.setup({
channelContent: this.defaultTicket.channelContent
});
return new Promise<Ticket>((resolve, reject) => resolve(ticket));
}
After trying to create a ticket, the program gives this error:
Bot\src\Structures\TicketManager.ts:47
await ticket.setup({ channelContent: this.defaultTicket.channelContent });
^
TypeError: ticket.setup is not a function
at TicketManager.createTicket (Bot\src\Structures\TicketManager.ts:47:22)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Event.run (Bot\src\Events\guildMemberAdd.ts:27:32)
The problem is that the method is perfectly typed and it even shows up in the autocomplete menu, but it always throws (no matter what I try to do) that error above.
I really hope somebody could help me figure this out, since it is a very important point in my bot development.
javascript
node.js
typescript
discord.js
downcast
0 Answers
Your Answer