I have a question how CDKs should handle deserialization of record & variant with opt fields if the label of an opt field is not known by the interface definition.
I asked the AI on the docs, but the AI says it is not explicitly stated what to do.
Question 1: record
Is my understanding correct that if a canister interface is defined as:
record { field1: opt text; field2: opt int }
but it receives this:
record { new: opt nat}
It should just ignore the new, and since field1 & field2 are not there, it must all be decoded as null.
Question 2: variant
And does it work the same for variant? So, if a canister interface is defined as:
variant { field1: opt text; field2: opt int }
but it receives this:
variant { new: opt nat}
It should just ignore the new, and it must be decoded as null.
For records you are correct. For variants, since a variant value always is a single case, nulling out other cases is not meaningful – we would need to map the unknown case to some other allowed case, but there is no canonical way to do so.
Consequently, it works in a dual fashion, with opt on the outside. That is, if an interface has a parameter defined as
opt variant { field1 : text; field2 : int }
but receives a value of type
opt variant { new : nat }
then it is decoded as null.
As a consequence, if you want a variant to be forward-compatible, you should always wrap it in an opt.
No, opt does not “propagate”. However, the general rule for opt is that it becomes null if the types cannot be made to match otherwise. That happens at the innermost opt where this fallback suffices to make the whole thing match.