I'm trying to define a method signature where a parameter should conform to an interface.
interface Command {}
class HelloCommand implements Command {
constructor(public readonly name: string) {}
}
type HandleCommandFn = (command: Command) => Promise<any>;
const handleHello: HandleCommandFn = (
command: HelloCommand
): Promise<string> => {
return Promise.resolve(`Hello ${command.name}`);
};
I get the following error from the compiler:
src/index.ts:9:7 - error TS2322: Type '(command: HelloCommand) => Promise<string>' is not assignable to type 'HandleCommandFn'.
Types of parameters 'command' and 'command' are incompatible.
Property 'name' is missing in type 'Command' but required in type 'HelloCommand'.
9 const handleHello: HandleCommandFn = (
I also tried the following variations :
type HandleCommandFn = <C extends Command>(command: C) => Promise<any>;
type HandleCommandFn = <C extends Command = Command>(command: C) => Promise<any>;
UPDATE
With the help of answers below, I managed to get the following piece of code (my goal was to define a type-safe method decorator) :
interface Command {
getDescription(): string;
}
type HandleCommandFn<C extends Command = Command> = (
command: C
) => Promise<any>;
function HandleCommand<C extends Command = Command>(
target: Object,
propertyKey: string | symbol,
descriptor: TypedPropertyDescriptor<HandleCommandFn<C>>
): void {
const method = descriptor.value;
if (method) {
// Do something
}
}
class HelloCommand implements Command {
constructor(public readonly name: string) {}
public getDescription(): string {
return "Say hello";
}
}
class HelloCommandHandler {
@HandleCommand // OK
public execute(command: HelloCommand): Promise<string> {
return Promise.resolve(`Hello ${command.name}`);
}
@HandleCommand // Error (wrong parameter type)
public execute2(command: string): Promise<string> {
return Promise.resolve(`Hello ${command}`);
}
@HandleCommand // Error (wrong return type)
public execute3(command: HelloCommand): string {
return `Hello ${command.name}`;
}
}