We value your privacy. We use cookies to enhance your experience on our site. By using this site you agree to our Privacy Policy.

Take advantage of nested JavaScript properties

One of the most requested features has finally landed: record and array property types for custom TypeScript and JavaScript components.

We can’t wait to see the amazing experiences that will come out using them!

Record 

Properties can now be grouped into a JavaScript class using the record property:

 1import {Component, Property} from '@wonderlandengine/api';
 2
 3class PlayerSettings {
 4    static Properties = {
 5        speed: Property.float(10.0),
 6        name: Property.string('Hero')
 7    };
 8}
 9
10export class PlayerManager extends Component {
11    static TypeName = 'player-manager';
12
13    static Properties = {
14        settings: Property.record(PlayerSettings)
15    };
16
17    start() {
18        console.log(this.settings); // Prints Player(10.0, 'Hero')
19        console.log(this.settings instanceof PlayerSettings); // true
20    }
21}
Custom Component Record & Array Properties

Note the style used to define the PlayerSettings class. Properties are declared in the same way for records and components.

Array 

It’s now also possible to create lists of properties using the array property:

 1import {Component, Property} from '@wonderlandengine/api';
 2
 3export class Downloader extends Component {
 4    static TypeName = 'downloader';
 5
 6    static Properties = {
 7        urls: Property.array(Property.string())
 8    };
 9
10    start() {
11        for(const url of this.urls) {
12            // Download the file pointed by `url`.
13        }
14    }
15}

Property.string() represents the type of the array elements. Arrays can only hold elements of a single type at once.

Mixed with the record property, complex types are now achievable:

 1import {Component, Property} from '@wonderlandengine/api';
 2
 3class Zombie {
 4    static Properties = {
 5        name: Property.string(),
 6        maxHealth: Property.float(100.0),
 7        mesh: Property.mesh(),
 8    };
 9}
10
11export class ZombieSpawner extends Component {
12    static TypeName = 'zombie-spawner';
13
14    static Properties = {
15        enemies: Property.array(Property.record(Zombie))
16    };
17
18    start() {
19        for(const zombie of this.enemies) {
20            const name = zombie.name;
21            const health = zombie.maxHealth;
22            // Spawn this mean zombie!
23        }
24    }
25}
Custom Component Record & Array Properties

The API also supports nested array properties (arrays of arrays):

 1import {Component, Property} from '@wonderlandengine/api';
 2
 3export class LevelGenerator extends Component {
 4    static TypeName = 'level-generator';
 5
 6    static Properties = {
 7        mapPiecesPerLevel: Property.array(Property.array(Property.string())),
 8    };
 9
10    start() {
11        // Prints something like:
12        // [
13        //    ['level_1_forest.map', 'level_1_mountains.map'],
14        //    ['level_2_beach.map', 'level_2_ocean.map', 'level_2_desert.map'],
15        //    ['level_3_underwater.map'],
16        // ]
17        console.log(this.mapPiecesPerLevel);
18    }
19}

TypeScript 

For TypeScript users, the new record and array property decorators make declaring complex component properties highly compact and intuitive:

 1import {Component, property, Property} from '@wonderlandengine/api';
 2
 3class Zombie {
 4    @property.string()
 5    name!: string;
 6
 7    @property.float(100)
 8    maxHealth!: number;
 9
10    @property.float(10)
11    damage!: number;
12}
13
14export class ZombieManager extends Component {
15    static TypeName = 'zombie-manager';
16
17    @property.array(Property.record(Zombie))
18    zombies!: Zombie[];
19}
Last Update: May 12, 2025

Stay up to date.