Skip to content

StringUnionProperty

StringUnionProperty<T extends string> (from scenerystack/axon) is a thin Property subclass for the common TypeScript idiom of using a string literal union ('small' | 'medium' | 'large') as a lightweight enumeration, instead of an EnumerationProperty backed by a Rich Enumeration class. It requires validValues at construction (there's no way to construct one without it) and derives the PhET-iO phetioValueType from that list automatically via StringUnionIO.

ts
import { StringUnionProperty } from 'scenerystack/axon';

type SizeChoice = 'small' | 'medium' | 'large';

const sizeProperty = new StringUnionProperty<SizeChoice>( 'medium', {
  validValues: [ 'small', 'medium', 'large' ]
} );

sizeProperty.value = 'large'; // fine
// sizeProperty.value = 'huge'; // would throw an assertion error — not in validValues

Constructor

ts
new StringUnionProperty<T extends string>( value: T, providedOptions: StringEnumerationPropertyOptions<T> )

Unlike plain Property, the options argument is requiredvalidValues has no default and must be supplied.

Options

StringUnionProperty accepts the same PropertyOptions<T> as Property, with two differences:

OptionEffect
validValuesRequired. The full list of legal string literal values — also used to build the phetioValueType
phetioValueTypeNot settable — StringUnionProperty always computes it from validValues via StringUnionIO

Everything else (tandem, units, reentrant, …) works exactly as it does on Property.

When to reach for this instead of EnumerationProperty

Use StringUnionProperty when the set of choices is small, has no associated behavior/data beyond the label itself, and is naturally expressed as a TypeScript string literal union already used elsewhere in your model's types. Use EnumerationProperty instead when the values need to carry additional data or methods (a full PhET "Rich Enumeration" class) — see the Enumeration Pattern for the tradeoffs between the two approaches.