Handling objects with optional properties.

386 views
Skip to first unread message

Tom Payne

unread,
Mar 11, 2013, 4:52:02 PM3/11/13
to closure-comp...@googlegroups.com
Hi,

I'm having difficultly trying to work out how to handle objects with optional properties.

A common JavaScript pattern is to simulate keyword arguments with an options argument, e.g.

var myX = new X({
  foo: 1
  bar: 'xyzzy'
});

The question is: how do I best represent this options object with the Closure Compiler?

If I use a typedef like:

/**
 * @typedef {{foo: number, bar: (string|undefined)}}
 */
MyOptions;

where bar is optional, then the following work:

/** @type {MyOptions} */
var a = {foo: 1, bar: 'xyzzy'}; // All properties defined

/** @type {MyOptions} */
var b = {foo: 1, bar: undefined}; // All properties defined

/** @type {MyOptions} */
var c = /** @type {MyOptions} */ ({foo: 1}); // Typecast

but the desired use case does not:

/** @type {MyOptions} */
var d = {foo 1}; // bar is not present, raises type error

Note that a and b behave differently from c and d, so it is entirely reasonable that the compiler complains about d (we override it in c).
a.hasOwnProperty('bar'); // -> true
b.hasOwnProperty('bar'); // -> true
c.hasOwnProperty('bar'); // -> false, but we cheated
d.hasOwnProperty('bar'); // -> false, so d is not an instance of MyOptions

Any hints on how to best handle this? Ideally I'd like to write an object literal like d and have the compiler interpret it as a MyOptions type, without needing a typecast.

Cheers,
Tom

Dimitris Vardoulakis

unread,
Mar 11, 2013, 5:10:36 PM3/11/13
to closure-comp...@googlegroups.com
There is no easy way to express that a property of an object may not exist sometimes. Your typedef says that a property bar will always exist on the object, but its value may be undefined, which is different from what you want.


--
 
---
You received this message because you are subscribed to the Google Groups "Closure Compiler Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to closure-compiler-d...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Dimitris

Tom Payne

unread,
Mar 11, 2013, 5:26:26 PM3/11/13
to closure-comp...@googlegroups.com
I agree - it is clear to me that the compiler is correct here.

Random ideas (I have no idea if any of these would actually work):

#1. Introduce a "void" type for properties, meaning that "if this property is absent, then that's OK and it should basically be ignored for type checking"

#2. Introduce an "@iAmWeaklyTyped" annotation for object literal types that tells the compiler that (a) missing properties are OK (as long as they can be undefined/void) and (b) ignores any properties that don't conflict with the defined properties.

I suspect that both of the above have subtle yet significant problems. Enlightenment welcome.

Regards,
Tom

Daniel Wirtz

unread,
Mar 12, 2013, 9:31:04 AM3/12/13
to closure-comp...@googlegroups.com, t...@tompayne.org
What about: @typedef {{a: number, b: string=}} like in function parameters. Would be pretty cool if closure compiler would handle this as "b may be omitted".

Dimitris Vardoulakis

unread,
Mar 12, 2013, 12:04:56 PM3/12/13
to closure-comp...@googlegroups.com, t...@tompayne.org
Yes, it'd definitely be nice. But type-system enhancements are not a top priority so don't hold your breath :)


On Tue, Mar 12, 2013 at 6:31 AM, Daniel Wirtz <dc...@dcode.io> wrote:
What about: @typedef {{a: number, b: string=}} like in function parameters. Would be pretty cool if closure compiler would handle this as "b may be omitted".

--
 
---
You received this message because you are subscribed to the Google Groups "Closure Compiler Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to closure-compiler-d...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Dimitris
Reply all
Reply to author
Forward
0 new messages