Incorrect optional typescript declaration generation?

Given following Motoko code:

actor Deck {
    private type DeckData = {
        header: ?Text;
    };
}

The SDK (v0.7.7) generates following type declaration:

export interface DeckData {
  'header' : [] | [string],
}

Isn’t that incorrect?

Shouldn’t be header?: string or header: string | null?

The optional value JS binding is defined this way:

The opt t type contains all the values of type t , plus the special null value. It is used to express that some value is optional, meaning that data might be present as some value of type t , or might be absent as the value null .

Yes, that’s why I don’t get why it generates Typescript declaration with arrays [] | [t] instead of t | null

I suspect its because the your suggested translation doesn’t work as intended for nested option types.

?? T would also translate to T* | null, conflating the two source null values.

But that doesn’t mean there isn’t a better translation that’s possible.

(noob question) do you mean, in my example, header: ?Text;?

I also think there’s a better approach for these bindings, but I haven’t done a formal proposal on them yet. Optional arguments are the least JavaScriptey design of them all now, though

All clear. Go for it, I would really not mind more JavaScript-like optional bindings.

Like I am looking forward to remove my helper :wink:.

const fromNullable = <T>(value: [] | [T]): T | undefined => {
  return value?.[0];
}
1 Like

Yeah, it’s better to return T | undefined instead of T | null, because the JavaScript null can also represent the Motoko (), so if you had to return ?() in Motoko, that would map to null | null in JS, which wouldn’t work.

Do you know if and when the TS types for Optional will ever be changed to be T | undefined by default when dfx build is run? Also, is there an easy way for devs to override that locally until it’s officially changed?

I’m curious why it wasn’t done like that in the beginning.

1 Like