From d812be48025b6a8fee58c6a97754e27095ed8f57 Mon Sep 17 00:00:00 2001 From: Jongsun Suh Date: Tue, 21 Oct 2025 10:55:58 -0400 Subject: [PATCH 1/6] Configure VSCode to use project typescript version --- .vscode/settings.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000000..25fa6215fdd --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "typescript.tsdk": "node_modules/typescript/lib" +} From b8bce30ecc89f104456ebf3b439246028b3af381 Mon Sep 17 00:00:00 2001 From: Jongsun Suh Date: Tue, 21 Oct 2025 10:59:31 -0400 Subject: [PATCH 2/6] Fix type error on `ComposableControllerMessenger` when used to instantiate `BaseController`, due to unnecessarily nested type definition ```ts Type 'ComposableControllerMessenger' is not assignable to type '"ComposableController:stateChange" extends (ComposableControllerEvents | ChildControllerStateChangeEvents<...>)["type"] ? ComposableControllerMessenger<...> : never'.ts(2322) ``` --- packages/composable-controller/src/ComposableController.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/composable-controller/src/ComposableController.ts b/packages/composable-controller/src/ComposableController.ts index 06421a64110..b4e52f97326 100644 --- a/packages/composable-controller/src/ComposableController.ts +++ b/packages/composable-controller/src/ComposableController.ts @@ -71,11 +71,9 @@ export type ChildControllerStateChangeEvents< > = ComposableControllerState extends Record< infer ControllerName extends string, - infer ControllerState + infer ControllerState extends StateConstraint > - ? ControllerState extends StateConstraint - ? ControllerStateChangeEvent - : never + ? ControllerStateChangeEvent : never; /** From f78159448755555f9f868dbc3d9c8d5964aaf6f0 Mon Sep 17 00:00:00 2001 From: Jongsun Suh Date: Tue, 21 Oct 2025 11:04:55 -0400 Subject: [PATCH 3/6] Add `ts-expect-error` for messenger subscriptions that are guaranteed to only happen for child controller events --- .../src/ComposableController.ts | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/composable-controller/src/ComposableController.ts b/packages/composable-controller/src/ComposableController.ts index b4e52f97326..45daac7946a 100644 --- a/packages/composable-controller/src/ComposableController.ts +++ b/packages/composable-controller/src/ComposableController.ts @@ -182,16 +182,18 @@ export class ComposableController< throw new Error(`${name} - ${INVALID_CONTROLLER_ERROR}`); } try { - this.messenger.subscribe( - `${name}:stateChange`, - (childState: StateConstraint) => { - this.update((state) => { - // Type assertion is necessary for property assignment to a generic type. This does not pollute or widen the type of the asserted variable. - // @ts-expect-error "Type instantiation is excessively deep" - (state as ComposableControllerStateConstraint)[name] = childState; - }); - }, - ); + this.messenger.subscribe< + // The type intersection with "ComposableController:stateChange" is added by one of the `Messenger.subscribe` overloads, but that constraint is unnecessary here, + // since this method only subscribes the messenger to child controller `stateChange` events. + // @ts-expect-error "Type '`${string}:stateChange`' is not assignable to parameter of type '"ComposableController:stateChange" & ChildControllerStateChangeEvents["type"]'." + ChildControllerStateChangeEvents['type'] + >(`${name}:stateChange`, (childState: StateConstraint) => { + this.update((state) => { + // Type assertion is necessary for property assignment to a generic type. This does not pollute or widen the type of the asserted variable. + // @ts-expect-error "Type instantiation is excessively deep" + (state as ComposableControllerStateConstraint)[name] = childState; + }); + }); } catch (error: unknown) { // False negative. `name` is a string type. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions From 304095543c10cda269ef05047f81fb6f505aa49e Mon Sep 17 00:00:00 2001 From: Jongsun Suh Date: Tue, 21 Oct 2025 12:10:19 -0400 Subject: [PATCH 4/6] Clearer generic param names --- packages/composable-controller/src/ComposableController.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/composable-controller/src/ComposableController.ts b/packages/composable-controller/src/ComposableController.ts index 45daac7946a..03bdb317341 100644 --- a/packages/composable-controller/src/ComposableController.ts +++ b/packages/composable-controller/src/ComposableController.ts @@ -70,10 +70,10 @@ export type ChildControllerStateChangeEvents< ComposableControllerState extends ComposableControllerStateConstraint, > = ComposableControllerState extends Record< - infer ControllerName extends string, - infer ControllerState extends StateConstraint + infer ChildControllerName extends string, + infer ChildControllerState extends StateConstraint > - ? ControllerStateChangeEvent + ? ControllerStateChangeEvent : never; /** From ee196cc6b7cb95dc7fb2aa5d8fdff3ca4f4e1f81 Mon Sep 17 00:00:00 2001 From: Jongsun Suh Date: Tue, 21 Oct 2025 12:25:23 -0400 Subject: [PATCH 5/6] Update eslint warning thresholds with warning reduction --- eslint-warning-thresholds.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/eslint-warning-thresholds.json b/eslint-warning-thresholds.json index a16cd0d14f3..fcfb3d02a3f 100644 --- a/eslint-warning-thresholds.json +++ b/eslint-warning-thresholds.json @@ -107,9 +107,6 @@ "packages/composable-controller/src/ComposableController.test.ts": { "import-x/namespace": 3 }, - "packages/composable-controller/src/ComposableController.ts": { - "@typescript-eslint/no-unused-vars": 1 - }, "packages/controller-utils/jest.environment.js": { "n/prefer-global/text-encoder": 1, "n/prefer-global/text-decoder": 1, From b3444fb970ecbb8b37742b4450464cf2e5a5730c Mon Sep 17 00:00:00 2001 From: Jongsun Suh Date: Tue, 21 Oct 2025 12:35:18 -0400 Subject: [PATCH 6/6] Update changelog --- packages/composable-controller/CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/composable-controller/CHANGELOG.md b/packages/composable-controller/CHANGELOG.md index e68d9c2e7b3..8bfbf05ac4c 100644 --- a/packages/composable-controller/CHANGELOG.md +++ b/packages/composable-controller/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Resolve incompatibility of `ChildControllerStateChangeEvents` type with `BaseController` (when used in the `Events` type argument of `ComposableControllerMessenger`) by removing unnecessary nested logic from definition ([#6904](https://github.com/MetaMask/core/pull/6904)) + - Also update generic parameter names `ControllerName` and `ControllerState` to `ChildControllerName`, `ChildControllerState` for reduced ambiguity. + ## [11.1.0] ### Added