Calling .props on a type that has .preProcessSnapshot doesn't update its snapshot type
Bug report
- [X] I've checked documentation and searched for existing issues
- [X] I've made sure my project is based on the latest MST version
minimal reproduction code
import { types as t, IType, IModelType, ReferenceIdentifier, SnapshotIn, SnapshotOut, Instance} from "mobx-state-tree";
// Define one model
const T2 = t.model({
id: t.identifier
});
interface IT2 extends Instance<typeof T2> {}
const T$1 = t.model({
id: t.identifier
}).preProcessSnapshot(s => s);
// Extend the extracted types to add another attribute:
interface ITSnapshotIn extends SnapshotIn<typeof T$1> {
window: ReferenceIdentifier;
}
interface ITSnapshotOut extends SnapshotOut<typeof T$1> {
window: ReferenceIdentifier;
}
interface IT extends Instance<typeof T$1> {
window: IT2;
}
// Use a proxy interface to improve error messages
interface ITRunType extends IType<ITSnapshotIn, ITSnapshotOut, IT> {}
// Extend T$1 with another attribute
const T$2 = T$1.props({
window: t.late(() => t.reference(T2))
});
// Final exposed type
export const T: ITRunType = T$2;
Describe the expected behavior
Code should compile
Describe the observed behavior
The last line fails with following error:
Type 'IModelType<{ id: ISimpleType<string>; } & { window: IReferenceType<IModelType<{ id: ISimpleType<string>; }, {}, _NotCustomized, _NotCustomized>>; }, {}, ModelCreationType<ExtractCFromProps<{ id: ISimpleType<string>; }>>, _NotCustomized>' is not assignable to type 'ITRunType'.
Types of property 'is' are incompatible.
Type '(thing: any) => thing is ModelCreationType<ExtractCFromProps<{ id: ISimpleType<string>; }>> | (ModelInstanceTypeProps<{ id: ISimpleType<string>; } & { window: IReferenceType<IModelType<{ id: ISimpleType<string>; }, {}, _NotCustomized, _NotCustomized>>; }> & IStateTreeNode<IModelType<{ id: ISimpleType<string>; } & { window: IReferenceType<IModelType<{ id: ISimpleType<string>; }, {}, _NotCustomized, _NotCustomized>>; }, {}, ModelCreationType<ExtractCFromProps<{ id: ISimpleType<string>; }>>, _NotCustomized>>)' is not assignable to type '(thing: any) => thing is ITSnapshotIn | (IT & IStateTreeNode<ITRunType>)'.
Type predicate 'thing is ModelCreationType<ExtractCFromProps<{ id: ISimpleType<string>; }>> | (ModelInstanceTypeProps<{ id: ISimpleType<string>; } & { window: IReferenceType<IModelType<{ id: ISimpleType<string>; }, {}, _NotCustomized, _NotCustomized>>; }> & IStateTreeNode<...>)' is not assignable to 'thing is ITSnapshotIn | (IT & IStateTreeNode<ITRunType>)'.
Type 'ModelCreationType<ExtractCFromProps<{ id: ISimpleType<string>; }>> | (ModelInstanceTypeProps<{ id: ISimpleType<string>; } & { window: IReferenceType<IModelType<{ id: ISimpleType<string>; }, {}, _NotCustomized, _NotCustomized>>; }> & IStateTreeNode<IModelType<{ id: ISimpleType<string>; } & { window: IReferenceType<IModelType<{ id: ISimpleType<string>; }, {}, _NotCustomized, _NotCustomized>>; }, {}, ModelCreationType<ExtractCFromProps<{ id: ISimpleType<string>; }>>, _NotCustomized>>)' is not assignable to type 'ITSnapshotIn | (IT & IStateTreeNode<ITRunType>)'.
Type 'ModelCreationType<ExtractCFromProps<{ id: ISimpleType<string>; }>>' is not assignable to type 'ITSnapshotIn | (IT & IStateTreeNode<ITRunType>)'.
Type 'ModelCreationType<ExtractCFromProps<{ id: ISimpleType<string>; }>>' is not assignable to type 'IT & IStateTreeNode<ITRunType>'.
Property 'window' is missing in type 'ModelCreationType<ExtractCFromProps<{ id: ISimpleType<string>; }>>' but required in type 'IT'. ⮐ [2322]
If I inspect the type of SnapshotIn<typeof T$2> I see the following:
type T3 = {
id: string;
} & Partial<ExtractCFromProps<{
id: ISimpleType<string>;
}>>
So it appears that once we define a snapshotPreProcessor through .preProcessSnapshot (even one that doesn't actually do anything), any types derived through .props will continue to have the same snapshot type irrespective of any new fields added.
The issue of course goes away if the .preProcessSnapshot invocation is removed (or moved to T3)
I have also observed that if we use types.compose instead of .props the error goes away.
I'd have expected extending through .props and .compose to have been identical operations but it doesn't seem that way.
That's because once you use preProcessSnapshot you are basically declaring what your custom snapshot in type is. Not sure if that can be fixed, hmm