terriajs
Version:
Geospatial data visualization platform.
50 lines (44 loc) • 1.75 kB
text/typescript
import { createTransformer, ITransformer } from "mobx-utils";
const undefinedObjectSymbol = Symbol("isUndefinedObject");
class UndefinedObject {
readonly [undefinedObjectSymbol]: true = true as const;
}
function isUndefinedObject(x: any): x is UndefinedObject {
return typeof x === "object" && undefinedObjectSymbol in x;
}
const undefinedObject = new UndefinedObject();
/**
* This function is identical to the MobX `createTransformer` function except that it allows `undefined` to be used as a transformed value.
* @param transformer The transformer function.
* @param onCleanup A function called when a memoized result is no longer needed.
*/
export default function createTransformerAllowUndefined<A, B>(
transformer: ITransformer<A | undefined, B>,
onCleanup?: (resultObject: B | undefined, sourceObject?: A) => void
): ITransformer<A | undefined, B> {
function unwrap(object: A | UndefinedObject): B {
return transformer(isUndefinedObject(object) ? undefined : object);
}
Object.defineProperty(unwrap, "name", {
value: (transformer.name || "anonymous") + "-allowUndefined"
});
const unwrapOnCleanup =
onCleanup === undefined
? undefined
: function (
resultObject: B | undefined,
sourceObject?: A | UndefinedObject
): void {
const unwrapped = isUndefinedObject(sourceObject)
? undefined
: sourceObject;
return onCleanup(resultObject, unwrapped);
};
const transformed: ITransformer<A | UndefinedObject, B> = createTransformer<
A | UndefinedObject,
B
>(unwrap, unwrapOnCleanup);
return function wrap(object: A | undefined): B {
return transformed(object === undefined ? undefinedObject : object);
};
}