If I have an actor method in Motoko that returns async ?(), how would I interpret that type in JavaScript/TypeScript? (The method returns async ?() to represent that either a) the method completed the operation successfully, i.e. ?(), or b) the method failed to complete, i.e. null. Maybe I should use Motoko’s Result interface to make that clearer?)
It seems like these are equivalent:
?() in Motoko opt null in Candid [] | [null] in JS/TS
I don’t understand why ?() in Motoko becomes opt null in Candid, but () in Motoko becomes () in Candid. I’m guessing that [null] in JS/TS means success, whereas [] in JS/TS means failure?
I don’t understand why ?() in Motoko becomes opt null in Candid, but () in Motoko becomes () in Candid
That seems inconsistent/non-compositional to me too, @rossberg@nomeata@chenyan do we have a bug here or is this intentional? I haven’t checked the translations with the compiler.
This is needed so that the idiomatic way to express enums as variants work out (if you omit the type from a variant tag you get () in Motoko, but null in Candid.)
I assume that your () is not the unit type but rather the empty argument sequence, and that indeed is mapped to the empty argument sequence in Candid. Note that Candid functions don’t take a single type, but always a sequence of types.
Oh interesting… Just to confirm then, in JS land [] represents the optional null, whereas [null] represents the Motoko type ()? That’s quite confusing and should probably be documented here.
Actually, the () in ?() is indeed the Motoko unit type. I’m using it as the return type of an actor method, i.e. async ?().
Hmm, I shouldn’t write technical stuff on the phone. What I wrote above wasn’t the full story (according to https://github.com/dfinity/motoko/blob/master/design/IDL-Motoko.md). Indeed, when exporting from Motoko to Candid, both () and Null maps to null. But when importing Candid into Motoko, null maps to Nullunless it is the type of a variant field, in which case it maps to ().
That seems to indicate that () in Motoko doesn’t always get mapped to null in Candid. It apparently also gets mapped to the empty return type (I have no idea what type that is here), which then gets mapped to undefined in JS.