Skip to content

Commit b611edd

Browse files
authored
Allow properties to be configurable (#32)
* Fix audit * Allow properties to be configurable
1 parent 40bbe50 commit b611edd

File tree

5 files changed

+42
-44
lines changed

5 files changed

+42
-44
lines changed

package-lock.json

Lines changed: 12 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/immutable-class/src/base-immutable/base-immutable.spec.ts

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -290,26 +290,35 @@ describe('BaseImmutable', () => {
290290
).toEqual({ fuel: 'electric', name: 'ford', passengers: [] });
291291
});
292292

293-
it('should fail to construct if property defined without "delcare"', () => {
294-
expect(() =>
295-
Bicycle.fromJS({
296-
fuel: 'potato',
297-
name: 'riva',
298-
}),
299-
).toThrow('Cannot redefine property: name');
293+
it('should not fail to construct if property defined without "declare"', () => {
294+
expect(() => Bicycle.fromJS({ fuel: 'potato', name: 'riva' })).not.toThrow();
295+
expect(() => Bicycle.fromJS({ fuel: 'potato', name: 'RIVA' })).toThrow(
296+
'Bicycle.name must be lowercase',
297+
);
300298
});
301299

302-
it('should fail on get() if getter defined without "delcare"', () => {
300+
it('should fail on get() if getter defined without "declare"', () => {
303301
const pope = Rider.fromJS({ name: 'pope' });
304302
expect(() => pope.get('name')).toThrowErrorMatchingInlineSnapshot(
305303
`"No getter was found for \\"name\\" but it is defined as a property. This might indicate that you are using \\"useDefineForClassFields\\" and forgot to use \\"declare\\" on an auto-generated getter property."`,
306304
);
307305
});
308306

309-
it('should fail on change() if changer defined without "delcare"', () => {
307+
it('should fail on change() if changer defined without "declare"', () => {
310308
const pope = Rider.fromJS({ name: 'pope' });
311309
expect(() => pope.change('name', 'papa')).toThrowErrorMatchingInlineSnapshot(
312310
`"No changer was found for \\"name\\" but it is defined as a property. This might indicate that you are using \\"useDefineForClassFields\\" and forgot to use \\"declare\\" on an auto-generated getter property."`,
313311
);
314312
});
313+
314+
it('allows values to be set in the constructor', () => {
315+
let car = Car.fromJS({ name: 'ford', fuel: 'electric', range: 150 });
316+
317+
expect(car.get('name')).toEqual('ford');
318+
expect(car.get('fuel')).toEqual('electric');
319+
expect(car.getRange()).toEqual(200);
320+
321+
car = car.changeRange(0);
322+
expect(car.getRange()).toEqual(0);
323+
});
315324
});

packages/immutable-class/src/base-immutable/base-immutable.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,7 @@ export abstract class BaseImmutable<ValueType, JSType>
118118
if (property.type === PropertyType.DATE) {
119119
pv = new Date(pv);
120120
} else if (property.immutableClass) {
121-
pv = (property.immutableClass as any).fromJS(
122-
pv,
123-
context ? contextTransform(context) : undefined,
124-
);
121+
pv = property.immutableClass.fromJS(pv, context ? contextTransform(context) : undefined);
125122
} else if (property.immutableClassArray) {
126123
if (!Array.isArray(pv)) throw new Error(`expected ${propertyName} to be an array`);
127124
const propertyImmutableClassArray: any = property.immutableClassArray;
@@ -178,7 +175,7 @@ export abstract class BaseImmutable<ValueType, JSType>
178175
for (const property of properties) {
179176
const propertyName = property.name;
180177
const propertyType = hasOwnProp(property, 'isDate') ? PropertyType.DATE : property.type;
181-
const pv = (value as any)[propertyName];
178+
const pv = value[propertyName];
182179

183180
if (pv == null) {
184181
if (propertyType === PropertyType.ARRAY) {
@@ -202,7 +199,7 @@ export abstract class BaseImmutable<ValueType, JSType>
202199
}
203200

204201
if (property.type === PropertyType.DATE) {
205-
if (isNaN(pv)) {
202+
if (isNaN(pv as any)) {
206203
throw new Error(`${this.constructor.name}.${propertyName} must be a Date`);
207204
}
208205
}
@@ -226,7 +223,7 @@ export abstract class BaseImmutable<ValueType, JSType>
226223

227224
Object.defineProperty(this, propertyName, {
228225
value: pv,
229-
configurable: false,
226+
configurable: true,
230227
enumerable: true,
231228
writable: false,
232229
});

packages/immutable-class/src/base-immutable/bicycle.mock.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,10 @@ export class Bicycle extends BaseImmutable<BicycleValue, BicycleJS> {
7272

7373
constructor(params: BicycleValue) {
7474
super(params);
75+
this.name = params.name;
7576
}
7677

77-
public name!: string; // This will cause a constructor error
78+
public readonly name: string;
7879
public declare fuel: string;
7980
}
8081
BaseImmutable.finalize(Bicycle);

packages/immutable-class/src/base-immutable/car.mock.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,16 @@ export class Car extends BaseImmutable<CarValue, CarJS> {
139139
public declare name: string;
140140
public declare fuel: string;
141141
public declare subCar: Car;
142-
public declare range: number;
142+
public readonly range: number | undefined;
143143
public declare createdOn: Date;
144144

145145
constructor(properties: CarValue) {
146146
super(properties);
147+
148+
if (properties.range != null) this.range = properties.range;
149+
if (this.fuel === 'electric' && this.range && this.range < 200) {
150+
this.range = 200;
151+
}
147152
}
148153

149154
public declare changeFuel: (fuel: string) => this;

0 commit comments

Comments
 (0)