mobx-keystone
Version:
A MobX powered state management solution based on data trees with first class support for TypeScript, snapshots, patches and much more
188 lines (187 loc) • 8.08 kB
TypeScript
import { SnapshotInOf, SnapshotOutOf } from '../snapshot/SnapshotOf';
import { LateTypeChecker, TypeChecker } from '../types/TypeChecker';
import { Flatten, IsNeverType, IsOptionalValue } from '../utils/types';
/**
* @ignore
*/
export declare const noDefaultValue: unique symbol;
/**
* A model property.
*/
export interface ModelProp<TPropValue, TPropCreationValue, TTransformedValue, TTransformedCreationValue, TIsRequired, TIsId extends boolean = false, THasSetter = never, TFromSnapshotOverride = never, TToSnapshotOverride = never> {
$valueType: TPropValue;
$creationValueType: TPropCreationValue;
$transformedValueType: TTransformedValue;
$transformedCreationValueType: TTransformedCreationValue;
$isRequired: TIsRequired;
$isId: TIsId;
$hasSetter: THasSetter;
$fromSnapshotOverride: TFromSnapshotOverride;
$toSnapshotOverride: TToSnapshotOverride;
_defaultFn: (() => TPropValue) | typeof noDefaultValue;
_defaultValue: TPropValue | typeof noDefaultValue;
_typeChecker: TypeChecker | LateTypeChecker | undefined;
_setter: boolean | "assign";
_isId: boolean;
_transform: {
transform: (original: unknown, model: object, propName: PropertyKey, setOriginalValue: (newOriginalValue: unknown) => void) => unknown;
untransform: (transformed: unknown, model: object, propName: PropertyKey) => unknown;
} | undefined;
_fromSnapshotProcessor?: (sn: unknown) => unknown;
_toSnapshotProcessor?: (sn: unknown) => unknown;
withSetter(): ModelProp<TPropValue, TPropCreationValue, TTransformedValue, TTransformedCreationValue, TIsRequired, TIsId, string, TFromSnapshotOverride, TToSnapshotOverride>;
/**
* @deprecated Setter methods are preferred.
*/
withSetter(mode: "assign"): ModelProp<TPropValue, TPropCreationValue, TTransformedValue, TTransformedCreationValue, TIsRequired, TIsId, string, TFromSnapshotOverride, TToSnapshotOverride>;
/**
* Sets a transform for the property instance value.
*
* @template TTV Transformed value type.
* @param transform Transform to be used.
* @returns
*/
withTransform<TTV>(transform: ModelPropTransform<NonNullable<TPropValue>, TTV>): ModelProp<TPropValue, TPropCreationValue, TTV | Extract<TPropValue, null | undefined>, TTV | Extract<TPropCreationValue, null | undefined>, TIsRequired, TIsId, THasSetter, TFromSnapshotOverride, TToSnapshotOverride>;
withSnapshotProcessor<FS = TFromSnapshotOverride, TS = TToSnapshotOverride, This extends AnyModelProp = this>(processor: {
fromSnapshot?: (sn: FS) => ModelPropFromSnapshot<This>;
toSnapshot?: (sn: ModelPropToSnapshot<This>) => TS;
}): ModelProp<TPropValue, TPropCreationValue, TTransformedValue, TTransformedCreationValue, TIsRequired, TIsId, THasSetter, FS, TS>;
}
/**
* The snapshot in type of a model property.
*/
export type ModelPropFromSnapshot<MP extends AnyModelProp> = IsNeverType<MP["$fromSnapshotOverride"], SnapshotInOf<MP["$creationValueType"]>, MP["$fromSnapshotOverride"]>;
/**
* The snapshot out type of a model property.
*/
export type ModelPropToSnapshot<MP extends AnyModelProp> = IsNeverType<MP["$toSnapshotOverride"], SnapshotOutOf<MP["$valueType"]>, MP["$toSnapshotOverride"]>;
/**
* A model prop transform.
*/
export interface ModelPropTransform<TOriginal, TTransformed> {
transform(params: {
originalValue: TOriginal;
cachedTransformedValue: TTransformed | undefined;
setOriginalValue(value: TOriginal): void;
}): TTransformed;
untransform(params: {
transformedValue: TTransformed;
cacheTransformedValue: () => void;
}): TOriginal;
}
/**
* Any model property.
*/
export type AnyModelProp = ModelProp<any, any, any, any, any, any, any, any, any>;
/**
* Model properties.
*/
export interface ModelProps {
[k: string]: AnyModelProp;
}
export type RequiredModelProps<MP extends ModelProps> = {
[K in keyof MP]: MP[K]["$isRequired"] & K;
}[keyof MP];
export type ModelPropsToUntransformedData<MP extends ModelProps> = Flatten<{
[k in keyof MP]: MP[k]["$valueType"];
}>;
export type ModelPropsToSnapshotData<MP extends ModelProps> = Flatten<{
[k in keyof MP]: ModelPropToSnapshot<MP[k]> extends infer R ? R : never;
}>;
export type ModelPropsToUntransformedCreationData<MP extends ModelProps> = {
[k in keyof MP]?: MP[k]["$creationValueType"];
} & {
[k in RequiredModelProps<MP>]: MP[k]["$creationValueType"];
};
export type ModelPropsToSnapshotCreationData<MP extends ModelProps> = Flatten<{
[k in keyof MP]?: ModelPropFromSnapshot<MP[k]> extends infer R ? R : never;
} & {
[k in {
[K in keyof MP]: IsNeverType<MP[K]["$fromSnapshotOverride"], MP[K]["$isRequired"] & K, // no override
IsOptionalValue<MP[K]["$fromSnapshotOverride"], never, K>>;
}[keyof MP]]: ModelPropFromSnapshot<MP[k]> extends infer R ? R : never;
}>;
export type ModelPropsToTransformedData<MP extends ModelProps> = Flatten<{
[k in keyof MP]: MP[k]["$transformedValueType"];
}>;
export type ModelPropsToTransformedCreationData<MP extends ModelProps> = {
[k in keyof MP]?: MP[k]["$transformedCreationValueType"];
} & {
[k in RequiredModelProps<MP>]: MP[k]["$transformedCreationValueType"];
};
export type ModelPropsToSetter<MP extends ModelProps> = Flatten<{
[k in keyof MP as MP[k]["$hasSetter"] & `set${Capitalize<k & string>}`]: (value: MP[k]["$transformedValueType"]) => void;
}>;
export type ModelIdProp<T extends string = string> = ModelProp<T, T | undefined, T, T | undefined, never, // not required
true>;
/**
* A property that will be used as model id, accessible through $modelId.
* Can only be used in models and there can be only one per model.
*/
export declare const idProp: ModelIdProp & {
/**
* Same as `idProp`, except that it might have an specific TypeScript string template as type.
* E.g. `typedIdProp<`custom-${string}`>()`
*/
typedAs<T extends string>(): ModelIdProp<T>;
};
/**
* @ignore
*/
export type OnlyPrimitives<T> = Exclude<T, object>;
/**
* A model prop that maybe / maybe not is optional, depending on if the value can take undefined.
*/
export type MaybeOptionalModelProp<TPropValue> = ModelProp<TPropValue, TPropValue, TPropValue, TPropValue, IsOptionalValue<TPropValue, never, string>>;
/**
* A model prop that is definitely optional.
*/
export type OptionalModelProp<TPropValue> = ModelProp<TPropValue, TPropValue | null | undefined, TPropValue, TPropValue | null | undefined, never>;
/**
* Defines a model property, with an optional function to generate a default value
* if the input snapshot / model creation data is `null` or `undefined`.
*
* Example:
* ```ts
* x: prop(() => 10) // an optional number, with a default value of 10
* x: prop<number[]>(() => []) // an optional number array, with a default empty array
* ```
*
* @template TValue Value type.
* @param defaultFn Default value generator function.
* @returns
*/
export declare function prop<TValue>(defaultFn: () => TValue): OptionalModelProp<TValue>;
/**
* Defines a model property, with an optional default value
* if the input snapshot / model creation data is `null` or `undefined`.
* You should only use this with primitive values and never with object values
* (array, model, object, etc).
*
* Example:
* ```ts
* x: prop(10) // an optional number, with a default value of 10
* ```
*
* @template TValue Value type.
* @param defaultValue Default primitive value.
* @returns
*/
export declare function prop<TValue>(defaultValue: OnlyPrimitives<TValue>): OptionalModelProp<TValue>;
/**
* Defines a model property with no default value.
*
* Example:
* ```ts
* x: prop<number>() // a required number
* x: prop<number | undefined>() // an optional number, which defaults to undefined
* ```
*
* @template TValue Value type.
* @returns
*/
export declare function prop<TValue>(): MaybeOptionalModelProp<TValue>;
/**
* @ignore
*/
export declare function getModelPropDefaultValue(propData: AnyModelProp): unknown | typeof noDefaultValue;