Looking into the decorator implementation, you could add more extended type validation by inferring the supposed method argument and return types based on the IDL types passed to the decorator. This would prevent bugs in TS where the IDL and function implementation differ.
import {IDL} from 'azle';
// TODO add more type mappings
type Mapping<T> =
T extends IDL.TextClass ? string
: T extends IDL.BoolClass ? boolean
: T extends IDL.NatClass ? bigint
: never;
// Make this get the typing based on Args generic from Mapping
export type MethodType<This, Args extends unknown[], Return> = (
this: This,
...args: Args extends unknown[] ? { [K in keyof Args]: Mapping<Args[K]> } : never
) => Mapping<Return>;
export type UpdateOptions = {
manual?: boolean;
hidden?: boolean;
};
export type OriginalMethod<This, Args extends unknown[], Return> = MethodType<
This,
Args,
Return
>;
export type Context<
This,
Args extends unknown[],
Return
> = ClassMethodDecoratorContext<This, MethodType<This, Args, Return>>;
export type DecoratorFunction<This, Args extends unknown[], Return> = (
originalMethod: OriginalMethod<This, Args, Return>,
context: Context<This, Args, Return>
) => void;
export function update<This, Args extends unknown[], Return>(
originalMethod: OriginalMethod<This, Args, Return>,
context: Context<This, Args, Return>
): void;
// The extends unknown can probably be changed to extends IDL[]
export function update<This, Args extends unknown[], Return>(
// Updated to use the generic types instead of IDL[]
paramIdlTypes?: Args,
returnIdlType?: Return,
options?: UpdateOptions
): DecoratorFunction<This, Args, Return>;
export function update<This, Args extends unknown[], Return>(
param1?: OriginalMethod<This, Args, Return> | IDL.Type[],
param2?: Context<This, Args, Return> | IDL.Type,
param3?: UpdateOptions
): void | DecoratorFunction<This, Args, Return> {
}
export default class {
message: string = 'Hello world!';
// If IDL types mismatch the function implementation, TS will throw an error.
@update([IDL.Text, IDL.Bool] as const, IDL.Text)
setMessage(message: string, x: boolean): string {
this.message = message;
return message;
}
}