diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 44fff6d5f..000000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "typings"]
- path = typings
- url = https://github.com/discordjs/discord.js-typings
diff --git a/.npmignore b/.npmignore
index 0ad23d8df..9d6674214 100644
--- a/.npmignore
+++ b/.npmignore
@@ -22,3 +22,5 @@ docs/
webpack.config.js
.github/
test/
+tsconfig.json
+tslint.json
diff --git a/package.json b/package.json
index 8287ade82..0caadd512 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
"docs:test": "docgen --source src --custom docs/index.yml",
"lint": "eslint src *.js",
"lint:fix": "eslint --fix src",
+ "lint:typings": "tslint index.d.ts discord.js-test.ts",
"build:browser": "webpack",
"prepublishOnly": "npm run test && NODE_ENV=production npm run build:browser"
},
@@ -54,6 +55,9 @@
"discord.js-docgen": "discordjs/docgen",
"eslint": "^5.0.1",
"json-filter-loader": "^1.0.0",
+ "tslint": "^3.15.1",
+ "tslint-config-typings": "^0.2.4",
+ "typescript": "^3.0.1",
"uglifyjs-webpack-plugin": "^1.1.8",
"webpack": "^4.5.0",
"webpack-cli": "^3.0.1"
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 000000000..63656868b
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "compilerOptions": {
+ "module": "commonjs",
+ "target": "es6",
+ "noImplicitAny": true,
+ "strictNullChecks": true,
+ "noEmit": true,
+ "forceConsistentCasingInFileNames": true
+ },
+ "files": [
+ "typings/index.d.ts"
+ ]
+}
\ No newline at end of file
diff --git a/tslint.json b/tslint.json
new file mode 100644
index 000000000..6cc6f6b26
--- /dev/null
+++ b/tslint.json
@@ -0,0 +1,62 @@
+{
+ "extends": [
+ "tslint-config-typings"
+ ],
+ "rules": {
+ "class-name": true,
+ "comment-format": [
+ true,
+ "check-space"
+ ],
+ "indent": [
+ true,
+ "tabs"
+ ],
+ "no-duplicate-variable": true,
+ "no-unused-variable": [false],
+ "no-eval": true,
+ "no-internal-module": true,
+ "no-trailing-whitespace": true,
+ "no-unsafe-finally": true,
+ "no-var-keyword": true,
+ "one-line": [
+ true,
+ "check-open-brace",
+ "check-whitespace"
+ ],
+ "quotemark": [
+ true,
+ "single"
+ ],
+ "semicolon": [
+ true,
+ "always"
+ ],
+ "triple-equals": [
+ true,
+ "allow-null-check"
+ ],
+ "typedef-whitespace": [
+ true,
+ {
+ "call-signature": "nospace",
+ "index-signature": "nospace",
+ "parameter": "nospace",
+ "property-declaration": "nospace",
+ "variable-declaration": "nospace"
+ }
+ ],
+ "variable-name": [
+ true,
+ "ban-keywords"
+ ],
+ "whitespace": [
+ true,
+ "check-branch",
+ "check-decl",
+ "check-operator",
+ "check-separator",
+ "check-type"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/typings b/typings
deleted file mode 160000
index db2a6e498..000000000
--- a/typings
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit db2a6e498bc625087cdd873a4af637539c4d4cfd
diff --git a/typings/discord.js-test.ts b/typings/discord.js-test.ts
new file mode 100644
index 000000000..6792dba87
--- /dev/null
+++ b/typings/discord.js-test.ts
@@ -0,0 +1,69 @@
+///
+
+import { Collector, Message, CollectorFilter, Client, CollectorHandler, MessageReaction, Collection, User, ReactionCollectorOptions, Snowflake } from 'discord.js';
+
+const client = new Client({
+ disableEveryone: false,
+ disabledEvents: ['GUILD_MEMBER_ADD']
+});
+
+client.on('message', (message) => {
+ if (message.content === 'hello') {
+ message.channel.sendMessage('o/');
+ }
+
+ const collector: ReactionCollector = new ReactionCollector(message,
+ (reaction: MessageReaction) => reaction.emoji.toString() === '👌',
+ { time: 30e3 });
+ collector.on('end', collected => console.log(collected));
+});
+
+client.login('dsfsd754.4fds4f68d4f6sd46f4s.7878easfdsgdfFDSIJIO');
+
+export class TestCollector extends Collector {
+ public filter: CollectorFilter;
+ public constructor(client: Client, filter: CollectorFilter, ) {
+ super(client, filter);
+ }
+
+ public handle(message: Message): CollectorHandler {
+ return { key: message.id, value: message };
+ }
+
+ public cleanup(): void {}
+ public postCheck(): null { return null; }
+}
+
+class ReactionCollector extends Collector {
+ public message: Message;
+ public users: Collection;
+ public total: number;
+ public options: ReactionCollectorOptions;
+ public constructor(message: Message, filter: CollectorFilter, options?: ReactionCollectorOptions) {
+ super(message.client, filter, options || {});
+ this.message = message;
+ this.users = new Collection();
+ this.total = 0;
+ this.client.on('messageReactionAdd', this.listener);
+ }
+
+ public handle(reaction: MessageReaction): CollectorHandler {
+ if (reaction.message.id !== this.message.id) { return null; }
+ return {
+ key: reaction.emoji.id || reaction.emoji.name,
+ value: reaction
+ };
+ }
+
+ public postCheck(reaction: MessageReaction, user: User): string {
+ this.users.set(user.id, user);
+ if (this.options.max && ++this.total >= this.options.max) { return 'limit'; }
+ if (this.options.maxEmojis && this.collected.size >= this.options.maxEmojis) { return 'emojiLimit'; }
+ if (this.options.maxUsers && this.users.size >= this.options.maxUsers) { return 'userLimit'; }
+ return null;
+ }
+
+ public cleanup(): void {
+ this.client.removeListener('messageReactionAdd', this.listener);
+ }
+}
diff --git a/typings/index.d.ts b/typings/index.d.ts
new file mode 100644
index 000000000..07b674f04
--- /dev/null
+++ b/typings/index.d.ts
@@ -0,0 +1,2151 @@
+// Type definitions for discord.js 12.0.0
+// Project: https://github.com/hydrabolt/discord.js
+// Definitions by:
+// acdenisSK (https://github.com/acdenisSK)
+// Zack Campbell (https://github.com/zajrik)
+// iCrawl (https://github.com/iCrawl)
+// License: MIT
+
+declare module 'discord.js' {
+ import { EventEmitter } from 'events';
+ import { Stream, Readable, Writable } from 'stream';
+ import { ChildProcess } from 'child_process';
+
+ export const version: string;
+
+//#region Classes
+
+ export class Activity {
+ constructor(presence: Presence, data: object);
+ public applicationID: Snowflake;
+ public assets: RichPresenceAssets;
+ public details: string;
+ public name: string;
+ public party: {
+ id: string;
+ size: [number, number];
+ };
+ public state: string;
+ public timestamps: {
+ start: Date;
+ end: Date;
+ };
+ public type: ActivityType;
+ public url: string;
+ public equals(activity: Activity): boolean;
+ }
+
+ export class Base {
+ constructor (client: Client);
+ public readonly client: Client;
+ public toJSON(...props: { [key: string]: boolean | string }[]): object;
+ public valueOf(): string;
+ }
+
+ export class BaseClient extends EventEmitter {
+ constructor(options?: ClientOptions);
+ private _intervals: Set;
+ private _timeouts: Set;
+ private readonly api: object;
+ private rest: object;
+
+ public options: ClientOptions;
+ public clearInterval(interval: NodeJS.Timer): void;
+ public clearTimeout(timeout: NodeJS.Timer): void;
+ public destroy(): void;
+ public setInterval(fn: Function, delay: number, ...args: any[]): NodeJS.Timer;
+ public setTimeout(fn: Function, delay: number, ...args: any[]): NodeJS.Timer;
+ public toJSON(...props: { [key: string]: boolean | string }[]): object;
+ }
+
+ class BroadcastDispatcher extends VolumeMixin(StreamDispatcher) {
+ public broadcast: VoiceBroadcast;
+ }
+
+ export class CategoryChannel extends GuildChannel {
+ public readonly children: Collection;
+ }
+
+ export class Channel extends Base {
+ constructor(client: Client, data: object);
+ public readonly createdAt: Date;
+ public readonly createdTimestamp: number;
+ public deleted: boolean;
+ public id: Snowflake;
+ public type: 'dm' | 'group' | 'text' | 'voice' | 'category' | 'unknown';
+ public delete(reason?: string): Promise;
+ public toString(): string;
+ }
+
+
+ export class Client extends BaseClient {
+ constructor(options?: ClientOptions);
+ private readonly _pingTimestamp: number;
+ private actions: object;
+ private manager: ClientManager;
+ private voice: object;
+ private ws: object;
+ private _eval(script: string): any;
+ private _pong(startTime: number): void;
+ private _validateOptions(options?: ClientOptions): void;
+
+ public broadcasts: VoiceBroadcast[];
+ public channels: ChannelStore;
+ public readonly emojis: GuildEmojiStore;
+ public guilds: GuildStore;
+ public readonly ping: number;
+ public pings: number[];
+ public presences: ClientPresenceStore;
+ public readyAt: Date;
+ public readonly readyTimestamp: number;
+ public shard: ShardClientUtil;
+ public readonly status: Status;
+ public token: string;
+ public readonly uptime: number;
+ public user: ClientUser;
+ public users: UserStore;
+ public readonly voiceConnections: Collection;
+ public createVoiceBroadcast(): VoiceBroadcast;
+ public destroy(): Promise;
+ public fetchApplication(id?: Snowflake): Promise;
+ public fetchInvite(invite: InviteResolvable): Promise;
+ public fetchVoiceRegions(): Promise>;
+ public fetchWebhook(id: Snowflake, token?: string): Promise;
+ public generateInvite(permissions?: number | PermissionResolvable[]): Promise;
+ public login(token?: string): Promise;
+ public sweepMessages(lifetime?: number): number;
+ public syncGuilds(guilds?: Guild[] | Collection): void;
+ public toJSON(): object;
+
+ public on(event: 'channelCreate' | 'channelDelete', listener: (channel: Channel) => void): this;
+ public on(event: 'channelPinsUpdate', listener: (channel: Channel, time: Date) => void): this;
+ public on(event: 'channelUpdate', listener: (oldChannel: Channel, newChannel: Channel) => void): this;
+ public on(event: 'clientUserGuildSettingsUpdate', listener: (clientUserGuildSettings: ClientUserGuildSettings) => void): this;
+ public on(event: 'clientUserSettingsUpdate', listener: (clientUserSettings: ClientUserSettings) => void): this;
+ public on(event: 'clientUserGuildSettingsUpdate', listener: (clientUserGuildSettings: ClientUserGuildSettings) => void): this;
+ public on(event: 'debug' | 'warn', listener: (info: string) => void): this;
+ public on(event: 'disconnect', listener: (event: any) => void): this;
+ public on(event: 'emojiCreate' | 'emojiDelete', listener: (emoji: GuildEmoji) => void): this;
+ public on(event: 'emojiUpdate', listener: (oldEmoji: GuildEmoji, newEmoji: GuildEmoji) => void): this;
+ public on(event: 'error', listener: (error: Error) => void): this;
+ public on(event: 'guildBanAdd' | 'guildBanRemove', listener: (guild: Guild, user: User) => void): this;
+ public on(event: 'guildCreate' | 'guildDelete' | 'guildUnavailable', listener: (guild: Guild) => void): this;
+ public on(event: 'guildMemberAdd' | 'guildMemberAvailable' | 'guildMemberRemove', listener: (member: GuildMember) => void): this;
+ public on(event: 'guildMembersChunk', listener: (members: Collection, guild: Guild) => void): this;
+ public on(event: 'guildMemberSpeaking', listener: (member: GuildMember, speaking: boolean) => void): this;
+ public on(event: 'guildMemberUpdate' | 'presenceUpdate' | 'voiceStateUpdate', listener: (oldMember: GuildMember, newMember: GuildMember) => void): this;
+ public on(event: 'guildUpdate', listener: (oldGuild: Guild, newGuild: Guild) => void): this;
+ public on(event: 'message' | 'messageDelete' | 'messageReactionRemoveAll', listener: (message: Message) => void): this;
+ public on(event: 'messageDeleteBulk', listener: (messages: Collection) => void): this;
+ public on(event: 'messageReactionAdd' | 'messageReactionRemove', listener: (messageReaction: MessageReaction, user: User) => void): this;
+ public on(event: 'messageUpdate', listener: (oldMessage: Message, newMessage: Message) => void): this;
+ public on(event: 'rateLimit', listener: (rateLimitData: RateLimitData) => void): this;
+ public on(event: 'ready' | 'reconnecting', listener: () => void): this;
+ public on(event: 'resumed', listener: (replayed: number) => void): this;
+ public on(event: 'roleCreate' | 'roleDelete', listener: (role: Role) => void): this;
+ public on(event: 'roleUpdate', listener: (oldRole: Role, newRole: Role) => void): this;
+ public on(event: 'typingStart' | 'typingStop', listener: (channel: Channel, user: User) => void): this;
+ public on(event: 'userNoteUpdate', listener: (user: UserResolvable, oldNote: string, newNote: string) => void): this;
+ public on(event: 'userUpdate', listener: (oldUser: User, newUser: User) => void): this;
+ public on(event: string, listener: Function): this;
+
+ public once(event: 'channelCreate' | 'channelDelete', listener: (channel: Channel) => void): this;
+ public once(event: 'channelPinsUpdate', listener: (channel: Channel, time: Date) => void): this;
+ public once(event: 'channelUpdate', listener: (oldChannel: Channel, newChannel: Channel) => void): this;
+ public once(event: 'clientUserGuildSettingsUpdate', listener: (clientUserGuildSettings: ClientUserGuildSettings) => void): this;
+ public once(event: 'clientUserSettingsUpdate', listener: (clientUserSettings: ClientUserSettings) => void): this;
+ public once(event: 'clientUserGuildSettingsUpdate', listener: (clientUserGuildSettings: ClientUserGuildSettings) => void): this;
+ public once(event: 'debug' | 'warn', listener: (info: string) => void): this;
+ public once(event: 'disconnect', listener: (event: any) => void): this;
+ public once(event: 'emojiCreate' | 'emojiDelete', listener: (emoji: GuildEmoji) => void): this;
+ public once(event: 'emojiUpdate', listener: (oldEmoji: GuildEmoji, newEmoji: GuildEmoji) => void): this;
+ public once(event: 'error', listener: (error: Error) => void): this;
+ public once(event: 'guildBanAdd' | 'guildBanRemove', listener: (guild: Guild, user: User) => void): this;
+ public once(event: 'guildCreate' | 'guildDelete' | 'guildUnavailable', listener: (guild: Guild) => void): this;
+ public once(event: 'guildMemberAdd' | 'guildMemberAvailable' | 'guildMemberRemove', listener: (member: GuildMember) => void): this;
+ public once(event: 'guildMembersChunk', listener: (members: Collection, guild: Guild) => void): this;
+ public once(event: 'guildMemberSpeaking', listener: (member: GuildMember, speaking: boolean) => void): this;
+ public once(event: 'guildMemberUpdate' | 'presenceUpdate' | 'voiceStateUpdate', listener: (oldMember: GuildMember, newMember: GuildMember) => void): this;
+ public once(event: 'guildUpdate', listener: (oldGuild: Guild, newGuild: Guild) => void): this;
+ public once(event: 'message' | 'messageDelete' | 'messageReactionRemoveAll', listener: (message: Message) => void): this;
+ public once(event: 'messageDeleteBulk', listener: (messages: Collection) => void): this;
+ public once(event: 'messageReactionAdd' | 'messageReactionRemove', listener: (messageReaction: MessageReaction, user: User) => void): this;
+ public once(event: 'messageUpdate', listener: (oldMessage: Message, newMessage: Message) => void): this;
+ public once(event: 'rateLimit', listener: (rateLimitData: RateLimitData) => void): this;
+ public once(event: 'ready' | 'reconnecting', listener: () => void): this;
+ public once(event: 'resumed', listener: (replayed: number) => void): this;
+ public once(event: 'roleCreate' | 'roleDelete', listener: (role: Role) => void): this;
+ public once(event: 'roleUpdate', listener: (oldRole: Role, newRole: Role) => void): this;
+ public once(event: 'typingStart' | 'typingStop', listener: (channel: Channel, user: User) => void): this;
+ public once(event: 'userNoteUpdate', listener: (user: UserResolvable, oldNote: string, newNote: string) => void): this;
+ public once(event: 'userUpdate', listener: (oldUser: User, newUser: User) => void): this;
+ public once(event: string, listener: Function): this;
+ }
+
+ export class ClientApplication extends Base {
+ constructor(client: Client, data: object);
+ public bot: object;
+ public botPublic: boolean;
+ public botRequireCodeGrant: boolean;
+ public cover: string;
+ public readonly createdAt: Date;
+ public readonly createdTimestamp: number;
+ public description: string;
+ public icon: string;
+ public id: Snowflake;
+ public name: string;
+ public owner: User;
+ public redirectURIs: string[];
+ public rpcApplicationState: boolean;
+ public rpcOrigins: string[];
+ public secret: string;
+ public coverImage(options?: AvatarOptions): string;
+ public createAsset(name: string, data: Base64Resolvable, type: 'big' | 'small' | 'Big' | 'Small'): Promise