diff --git a/__tests__/core/2230.test.ts b/__tests__/core/2230.test.ts index 9382666f9..b632515b7 100644 --- a/__tests__/core/2230.test.ts +++ b/__tests__/core/2230.test.ts @@ -1,5 +1,4 @@ //github.com/mobxjs/mobx-state-tree/issues/2230 - import { describe, test } from "bun:test" import { types, Instance } from "../../src/index" @@ -150,6 +149,31 @@ describe("2230 - type instantiation is excessively deep and possibly infinite", return self.prop41 } })) + .actions((self: IAction4) => ({ + getProp51(): string { + return self.prop51 + } + })) + .actions((self: IAction4) => ({ + getProp61(): string { + return self.prop61 + } + })) + .actions((self: IAction4) => ({ + getProp71(): string { + return self.prop71 + } + })) + .actions((self: IAction4) => ({ + getProp81(): string { + return self.prop81 + } + })) + .actions((self: IAction4) => ({ + getProp91(): string { + return self.prop91 + } + })) interface IAction5 extends Instance {} }) }) diff --git a/__tests__/core/type-system.test.ts b/__tests__/core/type-system.test.ts index 4bb571f89..614e1f371 100644 --- a/__tests__/core/type-system.test.ts +++ b/__tests__/core/type-system.test.ts @@ -1417,84 +1417,3 @@ test("#1627 - union dispatch function is typed", () => { types.null ) }) - -test("#2216 - should respect optionality when extending another type", () => { - const Base = types.model("ErrorStore", { value: types.string }).extend(self => ({ - actions: { - setValue(value?: string): boolean { - self.value = value || "test" - return true - }, - - setAnotherValue(value?: string): boolean { - self.value = value || "test" - return true - } - }, - views: { - get spam(): string { - return self.value - }, - - get eggs(): string { - return self.value - } - }, - state: { - anotherValue: "test" as string, - soManyValues: "test" as string - } - })) - - const Extended = Base.named("Extended") - .props({ - value: "test" - }) - .extend(self => ({ - actions: { - setValue(value: string): number { - self.value = value - return value.length - } - }, - views: { - get spam(): boolean { - return !!self.value - } - }, - state: { - anotherValue: "test" as string | undefined - } - })) - .actions(self => ({ - setAnotherValue(value: string): number { - self.value = value - return value.length - } - })) - .views(self => ({ - get eggs(): boolean { - return !!self.value - } - })) - .volatile(self => ({ - soManyValues: "test" as string | undefined - })) - - type InputSnapshot = SnapshotIn - type InstanceType = Instance - - assertTypesEqual(_ as InputSnapshot, _ as { value?: string }) - assertTypesEqual( - _ as InstanceType, - _ as { - value: string - setValue(value: string): number - setAnotherValue(value: string): number - spam: boolean - eggs: boolean - anotherValue: string | undefined - soManyValues: string | undefined - } - ) -}) diff --git a/src/types/complex-types/model.ts b/src/types/complex-types/model.ts index 7319d129a..3dcc0bec7 100644 --- a/src/types/complex-types/model.ts +++ b/src/types/complex-types/model.ts @@ -73,11 +73,6 @@ export interface ModelPropertiesDeclaration { [key: string]: ModelPrimitive | IAnyType } -/** intersect two object types, but omit keys of B from A before doing so */ -type OmitMerge = { - [K in keyof A as K extends keyof B ? never : K]: A[K] -} & B - /** * Unmaps syntax property declarations to a map of { propName: IType } * @@ -205,28 +200,23 @@ export interface IModelType< // so it is recommended to use pre/post process snapshot after all props have been defined props( props: PROPS2 - ): IModelType< - OmitMerge>, - OTHERS, - CustomC, - CustomS - > + ): IModelType, OTHERS, CustomC, CustomS> - views( + views( fn: (self: Instance) => V - ): IModelType, CustomC, CustomS> + ): IModelType actions( fn: (self: Instance) => A - ): IModelType, CustomC, CustomS> + ): IModelType - volatile( - fn: (self: Instance) => VS - ): IModelType, CustomC, CustomS> + volatile( + fn: (self: Instance) => TP + ): IModelType - extend( + extend( fn: (self: Instance) => { actions?: A; views?: V; state?: VS } - ): IModelType, CustomC, CustomS> + ): IModelType preProcessSnapshot>( fn: (snapshot: NewC) => WithAdditionalProperties> @@ -477,7 +467,7 @@ export class ModelType< return this.cloneAndEnhance({ properties }) } - volatile(fn: (self: Instance) => TP) { + volatile(fn: (self: Instance) => TP) { if (typeof fn !== "function") { throw new MstError( `You passed an ${typeof fn} to volatile state as an argument, when function is expected` @@ -514,7 +504,7 @@ export class ModelType< }) } - extend( + extend( fn: (self: Instance) => { actions?: A; views?: V; state?: VS } ) { const initializer = (self: Instance) => { @@ -531,7 +521,7 @@ export class ModelType< return this.cloneAndEnhance({ initializers: [initializer] }) } - views(fn: (self: Instance) => V) { + views(fn: (self: Instance) => V) { const viewInitializer = (self: Instance) => { this.instantiateViews(self, fn(self)) return self @@ -539,7 +529,7 @@ export class ModelType< return this.cloneAndEnhance({ initializers: [viewInitializer] }) } - private instantiateViews(self: this["T"], views: AnyObject): void { + private instantiateViews(self: this["T"], views: Object): void { // check views return if (!isPlainObject(views)) { throw new MstError(`views initializer should return a plain object containing views`)