dfinity / agent-js

A collection of libraries and tools for building software around the Internet Computer, in JavaScript.

Home Page:https://agent-js.icp.xyz

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Generated func types are possibly incorrect

lastmjs opened this issue · comments

Describe the bug

Generally the agent seems to generate Candid func types as TypeScript tuples [Principal, string]. But sometimes the agent is generating func types as actual functions, like (arg_0: Array<number>) => Promise<undefined>. I would think that is incorrect, and I'm having to work around this issue.

To Reproduce

Here's an example did file: https://github.com/demergent-labs/azle/blob/399_func_type_workarounds/examples/func_types/canisters/notifiers/notifiers.did#L1

Notice the Candid type for the func: type NotifierFunc = func (blob) -> () oneway;

Here's the generated TypeScript type for that did: https://github.com/demergent-labs/azle/blob/399_func_type_workarounds/examples/func_types/test/dfx_generated/notifiers/notifiers.did.d.ts#L2

Notice the TypeScript type for the func: export type NotifierFunc = (arg_0: Array<number>) => Promise<undefined>;

Expected behavior

I would expect func types to always be generated as TypeScript tuple types like [Principal, string].

Additional context

You can find the entire example application, with Candid and generated TypeScript files, here: https://github.com/demergent-labs/azle/tree/399_func_type_workarounds/examples/func_types

Are you using an old version of didc? Here is my output from the latest didc:

$ didc bind a.did -t ts
import type { Principal } from '@dfinity/principal';
import type { ActorMethod } from '@dfinity/agent';

export type NotifierFunc = ActorMethod<[Array<number>], undefined>;
export interface _SERVICE {
  'get_notifier' : ActorMethod<[], [Principal, string]>,
}

But your question remains for why NotifierFunc is a method type instead of (principal, string). This is expected, because we want to support the following the did file

type NotifierFunc = func (blob) -> () oneway;
service: {
    "get_notifier": () -> (NotifierFunc) query;
    f : NotifierFunc;
}

If NotifierFunc is (principal, string), we cannot type f.

@lastmjs does this answer resolve your question?

I'm not sure this resolves the question. I'm not sure the current behavior is the best choice, since it will break types for some use cases but not for others. In TS, the func will be a tuple TS type, so when importing from the agent, if it is not a tuple type then this will not work. I think something should be done to ensure that types can be used correctly for all use cases.