From aed3d71af84573364677f14415791064c5a65833 Mon Sep 17 00:00:00 2001 From: Kim Ode Date: Mon, 28 Apr 2025 16:07:51 +0200 Subject: [PATCH] Fix union of models or references #29 --- packages/mst-query/package-lock.json | 4 +-- packages/mst-query/package.json | 2 +- packages/mst-query/src/utils.ts | 9 +++++- packages/mst-query/tests/mstQuery.test.tsx | 32 ++++++++++++++++++++++ 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/packages/mst-query/package-lock.json b/packages/mst-query/package-lock.json index c8fa0d3..4ca8ed9 100644 --- a/packages/mst-query/package-lock.json +++ b/packages/mst-query/package-lock.json @@ -1,12 +1,12 @@ { "name": "mst-query", - "version": "4.2.0", + "version": "4.2.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mst-query", - "version": "4.2.0", + "version": "4.2.1", "license": "MIT", "dependencies": { "@wry/equality": "0.5.7" diff --git a/packages/mst-query/package.json b/packages/mst-query/package.json index 8723c57..698f3aa 100644 --- a/packages/mst-query/package.json +++ b/packages/mst-query/package.json @@ -1,6 +1,6 @@ { "name": "mst-query", - "version": "4.2.0", + "version": "4.2.1", "description": "Query library for mobx-state-tree", "source": "src/index.ts", "type": "module", diff --git a/packages/mst-query/src/utils.ts b/packages/mst-query/src/utils.ts index 7290db2..4af929a 100644 --- a/packages/mst-query/src/utils.ts +++ b/packages/mst-query/src/utils.ts @@ -32,7 +32,14 @@ export function getSubType(t: any, data?: any): any { return getSubType(t._subtype); } const subTypes = t._types.map((t: any) => getSubType(t, data)); - const modelWithProperties = subTypes.find((x: any) => isModelType(x) || isReferenceType(x)); + // Every subtype is a model type or reference type - return the union type and let mst + // handle reconciling the types. + if (subTypes.every((x: any) => isModelType(x) || isReferenceType(x))) { + return t; + } + // If we have a union of models and primitives (null/undefined), we need to find the first model or reference type + // to enumerate the properties of the object. + const modelWithProperties = subTypes.find((x: any) => isModelType(x) || isReferenceType(x)); if (modelWithProperties) { return getSubType(modelWithProperties, data); } diff --git a/packages/mst-query/tests/mstQuery.test.tsx b/packages/mst-query/tests/mstQuery.test.tsx index a581c8a..58c2246 100644 --- a/packages/mst-query/tests/mstQuery.test.tsx +++ b/packages/mst-query/tests/mstQuery.test.tsx @@ -1307,3 +1307,35 @@ test('initial data should only be set on mount', async () => { configureMobx({ enforceActions: 'observed' }); }); + +test('union of array models', () => { + const data = { + rules: [ + { + kind: 'FIXED', + fixedValue: 'Fixed value', + }, + { + kind: 'FORMAT', + formatValue: 'Formatted value', + }, + ], + }; + const Model = types.model('UnionArrayTestModel', { + rules: types.array( + types.union( + types.late(() => types.model('FixedModel', { + kind: types.literal('FIXED'), + fixedValue: types.string, + })), + types.model('FormatModel', { + kind: types.literal('FORMAT'), + formatValue: types.string, + }), + ), + ), + }); + const result = merge(data, Model, {}); + expect(result.rules[0].fixedValue).toBe('Fixed value'); + expect(result.rules[1].formatValue).toBe('Formatted value'); +});