-
Notifications
You must be signed in to change notification settings - Fork 642
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
(Typescript) frozen fields without a default always include undefined
as a possible type
#932
Comments
I've worked around this by creating a helper function:
and then using it when creating arrays of frozen:
The typings for v3 are great btw - model definition is simpler and the stronger typings meant I was able to catch quite a few subtle bugs that has slipped through previously! 🙏 |
Confirmed, both cases are fixed by #937. Great work @xaviergonz! Will release later |
Released as 3.0.2 |
I'm not sure if this is exactly related to this but I'm experiencing a similar issue using mst 3.10.0 with TS 3.2.2. When I access a frozen type that has array members I get types that are possibly undefined, whcich seems wrong (at least to me). For example:
Does this mean that this issue is not resolved or am I making some sort of conceptual error? |
Because undefined is a valid value to create an array type, since arrays are optional by default.
and therefore undefined would be a valid "array" when the runtime type checks it e.g. test("someTest", () => {
const ItemModel = types.model("Item", {
value: 42
})
const InventoryModel = types.model("Inventory", {
items: types.array(ItemModel)
})
const PersonModel = types.model("Person", {
inventory: types.frozen(InventoryModel)
})
// this does not fail in runtime
const person = PersonModel.create({ inventory: { items: undefined } })
expect(person.inventory.items).toBeUndefined()
}) |
@xaviergonz: Thanks for clearing that up. I guess I'm confused about what P.S. - Sorry for all the questions, but while you're here I would love to understand what the difference is between in and out types for snapshots. Why isn't the type serialized to not identical to the type serialized from? |
In an optional value the input json value might be undefined, but the output json will always contain a value, since the input will be transformed I usually think about it like this Therefore the input data (snapshot in) can be undefined, but the instance and the output data (snapshot out) won't |
I have:
Expected Behaviour:
For a model like this:
I would expect the type of
myField
to effectively beArray<MyFieldType>
.Observed Behaviour:
The type of
myField
is effectivelyArray<MyFieldType | undefined>
.I expected to have to use something like
myField: types.array(types.frozen<MyInterface | undefined>())
or wrap in a maybe/optional to get this.Detail
I'm looking to update from version 2.x to version 3 to take advantage of improvements, and have found this a little inconsistent:
undefined
to be a valid value of the field.frozen
fields, the defaulting functionality appears to be already included (as an optional constructor) rather than using maybe/optional.This means that when wanting a field defined as an array of frozen objects, one of the following trade-offs must be used:
field: types.array(types.frozen<MyItemType>()),
and then always have to check if individual items areundefined
(and pushingundefined
is allowed)field: types.array(types.frozen<MyItemType>(myDefaultItemInstance)),
which has the correct typing, but the default instance is never used and can be difficult to come up with for complicated types (think large hierarchical business entities read from a server).Questions:
Example codesandbox available here: https://codesandbox.io/s/5xj57x0ym4 - please see
src/models/Frozen.ts
and thecompareFrozenFields
action.Thanks very much!
Edit:
I've also found that when a frozen field should be optionally
undefined
, I still have to usetypes.maybe
otherwise when I try to use that type, typescript insists that the field must be present.For example, the following will show an error for the value passed to
types.optional
(it wants{ myField: undefined }
):But this is fine:
Even though the type of
ModelA.myField
is the same in both cases (MyType | undefined
). This may be the way it's supposed to work, but I thought it worth mentioning.The text was updated successfully, but these errors were encountered: