TypeScript does not recognize overriding mandatory property with optional one in sub-model
andreykurilin opened this issue · 6 comments
Minimal reproduction code
import { types } from 'mobx-state-tree';
export const ErrorStore = types
.model('ErrorStore', {
value: '',
})
.actions((self) => ({
set(value: string) {
self.value = value;
},
reset() {
self.value = '';
},
}))
.views((self) => ({
get formattedValue() {
return self.value;
},
}));
export const NoDisplayError = ErrorStore.named('NoDisplayError').views(() => ({
get formattedValue() {
return undefined;
},
}));
const InputStore = types.model("InputStore", {
value: "",
// developer should explicitly specify whether validation errors should be displayed or not
error: types.union(ErrorStore, NoDisplayError)
});
const PasswordInputStore = InputStore.named("PasswordInputStore").props({
// we have strict requirements for password, so validation errors should be displayed by default
error: types.optional(types.union(ErrorStore, NoDisplayError), () => ErrorStore.create({}))
});
const passwordS = PasswordInputStore.create({});
Describe the expected behavior
Initialization of PasswordInputStore
should not require specifying optional error
property.
Describe the observed behavior
TypeScript fails as error
property is not provided.
TS2345: Argument of type '{}' is not assignable to parameter of type 'ModelCreationType<{ value: string | undefined; error: EmptyObject & Partial<{ value: string | undefined; }>; }>'.
Property 'error' is missing in type '{}' but required in type '{ error: EmptyObject & Partial<{ value: string | undefined; }>; }'.
Thanks for the issue report @andreykurilin, and I'm sorry for the inconvenience!
I see @thegedge has assigned this to himself, so I expect good things here.
I put together a CodeSandbox with the repro code in case that helps demonstrate the issue for others: https://codesandbox.io/p/sandbox/g3w8ft?file=%2Fsrc%2Findex.ts%3A8%2C15
Sorry for the delay, but it's been really busy for me lately.
Thought I'd explore what's happening here:
Makes sense that if you have PropsA & PropsB
with one having a required prop and the other not, the required prop wins. Since the way props
works in MST is to "clobber" properties, I think the fix will be simple: Omit<PropsA, keyof PropsB> & PropsB
.
[EDIT]
I suspect we may want to do this for anything else that "clobbers"; like views
, actions
, extend
, and so on.