immutable-class
Version:
A template for creating immutable classes
137 lines (136 loc) • 3.69 kB
JavaScript
import { BaseImmutable, PropertyType } from './base-immutable';
export class Driver extends BaseImmutable {
static fromJS(params) {
return new Driver(BaseImmutable.jsToValue(Driver.PROPERTIES, params));
}
constructor(params) {
super(params);
}
}
Object.defineProperty(Driver, "PROPERTIES", {
enumerable: true,
configurable: true,
writable: true,
value: [{ name: 'name', defaultValue: null }]
});
BaseImmutable.finalize(Driver);
Driver.POPE = Driver.fromJS({ name: 'the pope' });
function ensureNonNegative(n) {
if (n < 0)
throw new Error('must non negative positive');
}
export class Car extends BaseImmutable {
static isCar(car) {
return car instanceof Car;
}
static fromJS(properties) {
return new Car(BaseImmutable.jsToValue(Car.PROPERTIES, properties, Car.BACK_COMPATS));
}
constructor(properties) {
super(properties);
Object.defineProperty(this, "range", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
if (properties.range != null)
this.range = properties.range;
if (this.fuel === 'electric' && this.range && this.range < 200) {
this.range = 200;
}
}
getSubCar() {
const { name, subCar } = this;
if (subCar)
return subCar;
if (name === 'ford')
return Car.fromJS({ name: 'pinto', fuel: 'gas' });
if (name === 'toyota')
return Car.fromJS({ name: 'prius', fuel: 'electric' });
return null;
}
changeRange(n) {
const value = this.valueOf();
const { fuel } = value;
if (fuel === 'electric') {
value.range = n > 400 ? 400 : n;
return new Car(value);
}
if (fuel === 'diesel') {
value.range = n > 2000 ? 2000 : n;
return new Car(value);
}
value.range = n;
return new Car(value);
}
}
Object.defineProperty(Car, "PROPERTIES", {
enumerable: true,
configurable: true,
writable: true,
value: [
{
name: 'name',
validate: (n) => {
if (n.toLowerCase() !== n)
throw new Error('must be lowercase');
},
},
{
name: 'fuel',
defaultValue: 'electric',
possibleValues: ['gas', 'diesel', 'electric'],
},
{
name: 'subCar',
defaultValue: null,
immutableClass: Car,
},
{
name: 'range',
defaultValue: 100,
validate: [BaseImmutable.ensure.number, ensureNonNegative],
},
{
name: 'relatedCars',
defaultValue: [],
immutableClassArray: Car,
},
{
name: 'createdOn',
defaultValue: null,
type: PropertyType.DATE,
},
{
name: 'owners',
defaultValue: null,
emptyArrayIsOk: true,
},
{
name: 'driver',
defaultValue: Driver.POPE,
immutableClass: Driver,
},
{
name: 'passengers',
type: PropertyType.ARRAY,
},
]
});
Object.defineProperty(Car, "BACK_COMPATS", {
enumerable: true,
configurable: true,
writable: true,
value: [
{
condition: (js) => {
return js.fuelType;
},
action: (js) => {
js.fuel = js.fuelType;
},
},
]
});
BaseImmutable.finalize(Car);