How do I use Parameters and ReturnType with generics?

Viewed 47

I'm trying to create a helper function for a method of a property that's declared through a generic type parameter. Unfortunately, I can only get the code to compile when I use a concrete type and not the generic type parameter. Minimal example below.

// Adapted from https://github.com/abalabahaha/eris, licence MIT
declare class Message<T extends Textable = Textable> {
    channel: T;
}
interface Textable {
    createMessage(content: string, file?: string | string[]): Promise<Message>;
}

function test<T extends Textable>(...args: Parameters<T["createMessage"]>) {
    void args;
}

// This compiles when the generic isn't used and Textable is specified explicitly
export default async function reply<T extends Textable>(
    msg: Message<T>,
    ...args: Parameters<Textable["createMessage"]>
): ReturnType<Textable["createMessage"]> {
    test(...args);
    return await msg.channel.createMessage(...args);
}

// This does not compile when the generic is actually used
export default async function reply<T extends Textable>(
    msg: Message<T>,
    ...args: Parameters<T["createMessage"]>
): ReturnType<T["createMessage"]> { // The return type of an async function or method must be the global Promise<T> type. Did you mean to write 'Promise<Message<Textable>>'?
    test(...args); // still compiles
    msg.channel.createMessage(args[0], args[1]); // still compiles
    return await msg.channel.createMessage(...args); // Expected 1-2 arguments, but got 0 or more. An argument for 'content' was not provided.
}

Playground Link

0 Answers
Related