Skip to content

assertHasProperties and assertMutuallyExclusiveOptions ​

assertHasProperties and assertMutuallyExclusiveOptions (from scenerystack/phet-core) are development-time assertion helpers for validating an object's shape at a call site — the first checks that certain named members exist (anywhere in the prototype chain), the second checks that certain groups of option keys are never supplied together. Both are no-ops in a production build; like the rest of SceneryStack's assert && assert(...) convention, they only run when assertions are enabled, so they should guard invariants, not carry runtime logic.

ts
import { assertHasProperties, assertMutuallyExclusiveOptions } from 'scenerystack/phet-core';

assertHasProperties ​

ts
assertHasProperties( object: unknown, properties: string[] ): void

Asserts that object has an own property or an inherited (prototype-chain) property for every name in properties. Useful for validating a duck-typed dependency (e.g. "this object needs to look like a TColor") without importing its concrete class.

ts
assertHasProperties( someNode, [ 'getOpacity', 'opacity', '_opacity' ] ); // no error if all three exist somewhere in the chain
assertHasProperties( { flower: 2 }, [ 'tree' ] );                        // throws: property not defined: tree

assertMutuallyExclusiveOptions ​

ts
assertMutuallyExclusiveOptions( options: object | null | undefined, ...sets: string[][] ): void

Asserts that at most one of the given key-sets has any of its keys present in options — pass one string[] per mutually-exclusive group. options may be null/undefined (treated as "nothing set," so it always passes).

Only one of the provided sets may have any of its keys present at all — using multiple keys within the same set is fine:

ts
assertMutuallyExclusiveOptions( { tree: 1, flower: 2 }, [ 'tree' ], [ 'flower' ] );               // throws - one key used from each of the two sets
assertMutuallyExclusiveOptions( { flower: 2 }, [ 'tree' ], [ 'flower' ] );                        // fine - only the second set is used
assertMutuallyExclusiveOptions( { tree: 1, mountain: 2 }, [ 'tree', 'mountain' ], [ 'flower' ] ); // fine - both used keys belong to the first set

Summary ​

FunctionChecksThrows when
assertHasProperties( object, properties )Named members exist (own or inherited)Any name in properties is missing everywhere in the chain
assertMutuallyExclusiveOptions( options, ...sets )At most one option-key group is usedKeys from more than one of the provided sets are present in options

Both are guarded by the global assertion flag, not a manual if

Call these directly — don't wrap them in assert && assertHasProperties(...) yourself the way you would with window.assert; these two functions already check internally whether assertions are enabled and no-op if not, matching the convention used by merge and other phet-core runtime checks.