Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/spiffytech/mobx into spif…
Browse files Browse the repository at this point in the history
…fytech-master
  • Loading branch information
mweststrate committed Sep 23, 2016
2 parents edc65e1 + b6d04ff commit 3bac300
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 7 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# 2.5.2

* Observable objects can now have a type: `IObservableObject`, see [#484](https://github.com/mobxjs/mobx/pull/484) by @spiffytech

# 2.5.1

* Computed properties can now be created by using getter / setter functions. This is the idiomatic way to introduce computed properties from now on:
Expand Down
5 changes: 3 additions & 2 deletions src/api/observable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {computed} from "./computeddecorator";
import {isPlainObject, invariant, deprecated} from "../utils/utils";
import {observableDecorator} from "./observabledecorator";
import {isObservable} from "./isobservable";
import {IObservableObject} from "../types/observableobject";
import {IObservableArray, ObservableArray} from "../types/observablearray";

/**
Expand All @@ -15,7 +16,7 @@ export function observable(target: Object, key: string, baseDescriptor?: Propert
export function observable<T>(value: T[]): IObservableArray<T>;
export function observable<T, S extends Object>(value: () => T, thisArg?: S): IObservableValue<T>;
export function observable<T extends string|number|boolean|Date|RegExp|Function|void>(value: T): IObservableValue<T>;
export function observable<T extends Object>(value: T): T;
export function observable<T extends Object>(value: T): T & IObservableObject;
export function observable(v: any = undefined, keyOrScope?: string | any) {
if (typeof arguments[1] === "string")
return observableDecorator.apply(null, arguments);
Expand Down Expand Up @@ -55,4 +56,4 @@ export function getTypeOfValue(value): ValueType {
if (typeof value === "object")
return isPlainObject(value) ? ValueType.PlainObject : ValueType.ComplexObject;
return ValueType.Reference; // safe default, only refer by reference..
}
}
2 changes: 1 addition & 1 deletion src/mobx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export { IComputedValue } from "./core/com
export { asReference, asFlat, asStructure, asMap } from "./types/modifiers";
export { IInterceptable, IInterceptor } from "./types/intercept-utils";
export { IListenable } from "./types/listen-utils";
export { IObjectWillChange, IObjectChange, isObservableObject } from "./types/observableobject";
export { IObjectWillChange, IObjectChange, IObservableObject, isObservableObject } from "./types/observableobject";
export { /* 3.0: IValueDidChange, */ IValueWillChange, IObservableValue } from "./types/observablevalue";

export { IObservableArray, IArrayWillChange, IArrayWillSplice, IArrayChange, IArraySplice, isObservableArray, fastArray } from "./types/observablearray";
Expand Down
10 changes: 7 additions & 3 deletions src/types/observableobject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import {hasInterceptors, IInterceptable, registerInterceptor, interceptChange} f
import {IListenable, registerListener, hasListeners, notifyListeners} from "./listen-utils";
import {isSpyEnabled, spyReportStart, spyReportEnd} from "../core/spy";

export interface IObservableObject {
"observable-object": IObservableObject;
}

// In 3.0, change to IObjectDidChange
export interface IObjectChange {
name: string;
Expand Down Expand Up @@ -214,11 +218,11 @@ function notifyPropertyAddition(adm, object, name: string, newValue) {
spyReportEnd();
}

export function isObservableObject(thing): boolean {
export function isObservableObject<T>(thing: T): thing is T & IObservableObject {
if (typeof thing === "object" && thing !== null) {
// Initializers run lazily when transpiling to babel, so make sure they are run...
runLazyInitializers(thing);
return thing.$mobx instanceof ObservableObjectAdministration;
return (thing as T & {$mobx: any}).$mobx instanceof ObservableObjectAdministration;
}
return false;
}
}
41 changes: 40 additions & 1 deletion test/typescript-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/// <reference path='tape.d.ts' />
import {
observe, computed, observable, asStructure, autorun, autorunAsync, extendObservable, action,
IObservableArray, IArrayChange, IArraySplice, IObservableValue, isObservable, isObservableObject,
IObservableObject, IObservableArray, IArrayChange, IArraySplice, IObservableValue, isObservable, isObservableObject,
extras, Atom, transaction, IObjectChange, spy, useStrict, isAction
} from "../lib/mobx";
import * as test from 'tape';
Expand Down Expand Up @@ -959,6 +959,45 @@ test('computed getter / setter for plan objects should succeed (typescript)', fu
t.equal(b.propX, 8);

t.deepEqual(values, [6, 8])
t.end()
})

test("484 - observable objects are IObservableObject", t => {
const needs_observable_object = (o: IObservableObject): any => null;
const o = observable({stuff: "things"});

needs_observable_object(o);
t.pass();
t.end();
});

test("484 - observable objects are still type T", t => {
const o = observable({stuff: "things"});
o.stuff = "new things";
t.pass();
t.end();
});

test("484 - isObservableObject type guard includes type T", t => {
const o = observable({stuff: "things"});
if(isObservableObject(o)) {
o.stuff = "new things";
t.pass();
} else {
t.fail("object should have been observable");
}
t.end();
});

test("484 - isObservableObject type guard includes type IObservableObject", t => {
const requires_observable_object = (o: IObservableObject): void => null;
const o = observable({stuff: "things"});

if(isObservableObject(o)) {
requires_observable_object(o);
t.pass();
} else {
t.fail("object should have been IObservableObject");
}
t.end();
});

0 comments on commit 3bac300

Please sign in to comment.