diff --git a/packages/address-book-controller/src/AddressBookController.ts b/packages/address-book-controller/src/AddressBookController.ts index 1101dffc94a..cd96f5355c1 100644 --- a/packages/address-book-controller/src/AddressBookController.ts +++ b/packages/address-book-controller/src/AddressBookController.ts @@ -78,7 +78,7 @@ export class AddressBookController extends BaseControllerV1< /** * Name of this controller used during composition */ - override name = 'AddressBookController'; + override name = 'AddressBookController' as const; /** * Creates an AddressBookController instance. diff --git a/packages/assets-controllers/src/AccountTrackerController.ts b/packages/assets-controllers/src/AccountTrackerController.ts index 6c8479dc2b7..3596790358b 100644 --- a/packages/assets-controllers/src/AccountTrackerController.ts +++ b/packages/assets-controllers/src/AccountTrackerController.ts @@ -112,7 +112,7 @@ export class AccountTrackerController extends StaticIntervalPollingControllerV1< /** * Name of this controller used during composition */ - override name = 'AccountTrackerController'; + override name = 'AccountTrackerController' as const; private readonly getIdentities: () => PreferencesState['identities']; diff --git a/packages/assets-controllers/src/AssetsContractController.ts b/packages/assets-controllers/src/AssetsContractController.ts index 71cad853906..b9dd83602a6 100644 --- a/packages/assets-controllers/src/AssetsContractController.ts +++ b/packages/assets-controllers/src/AssetsContractController.ts @@ -107,7 +107,7 @@ export class AssetsContractController extends BaseControllerV1< /** * Name of this controller used during composition */ - override name = 'AssetsContractController'; + override name = 'AssetsContractController' as const; private readonly getNetworkClientById: NetworkController['getNetworkClientById']; diff --git a/packages/assets-controllers/src/NftController.ts b/packages/assets-controllers/src/NftController.ts index ff712bf8bf3..90ae8560cfe 100644 --- a/packages/assets-controllers/src/NftController.ts +++ b/packages/assets-controllers/src/NftController.ts @@ -935,7 +935,7 @@ export class NftController extends BaseControllerV1 { /** * Name of this controller used during composition */ - override name = 'NftController'; + override name = 'NftController' as const; private readonly getERC721AssetName: AssetsContractController['getERC721AssetName']; diff --git a/packages/assets-controllers/src/TokenRatesController.ts b/packages/assets-controllers/src/TokenRatesController.ts index 42e65672b5c..e065d2e40b5 100644 --- a/packages/assets-controllers/src/TokenRatesController.ts +++ b/packages/assets-controllers/src/TokenRatesController.ts @@ -172,7 +172,7 @@ export class TokenRatesController extends StaticIntervalPollingControllerV1< /** * Name of this controller used during composition */ - override name = 'TokenRatesController'; + override name = 'TokenRatesController' as const; private readonly getNetworkClientById: NetworkController['getNetworkClientById']; diff --git a/packages/composable-controller/CHANGELOG.md b/packages/composable-controller/CHANGELOG.md index eb07c36f282..ee846caee9a 100644 --- a/packages/composable-controller/CHANGELOG.md +++ b/packages/composable-controller/CHANGELOG.md @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Adds and exports new types: ([#3952](https://github.com/MetaMask/core/pull/3952)) + - `RestrictedControllerMessengerConstraint`, which is the narrowest supertype of all controller-messenger instances. + - `LegacyControllerStateConstraint`, a universal supertype for the controller state object, encompassing both BaseControllerV1 and BaseControllerV2 state. + - `ComposableControllerStateConstraint`, the narrowest supertype for the composable controller state object. + +### Changed + +- **BREAKING:** The `ComposableController` class is now a generic class that expects one generic argument `ComposableControllerState` ([#3952](https://github.com/MetaMask/core/pull/3952)). + - **BREAKING:** For the `ComposableController` class to be typed correctly, any of its child controllers that extend `BaseControllerV1` must have an overridden `name` property that is defined using the `as const` assertion. + ## [6.0.1] ### Fixed diff --git a/packages/composable-controller/src/ComposableController.test.ts b/packages/composable-controller/src/ComposableController.test.ts index ca5df665efd..6ab79f223c8 100644 --- a/packages/composable-controller/src/ComposableController.test.ts +++ b/packages/composable-controller/src/ComposableController.test.ts @@ -27,9 +27,9 @@ type FooControllerEvent = { type FooMessenger = RestrictedControllerMessenger< 'FooController', never, - FooControllerEvent, + FooControllerEvent | QuzControllerEvent, never, - never + QuzControllerEvent['type'] >; const fooControllerStateMetadata = { @@ -60,6 +60,50 @@ class FooController extends BaseController< } } +type QuzControllerState = { + quz: string; +}; +type QuzControllerEvent = { + type: `QuzController:stateChange`; + payload: [QuzControllerState, Patch[]]; +}; + +type QuzMessenger = RestrictedControllerMessenger< + 'QuzController', + never, + QuzControllerEvent, + never, + never +>; + +const quzControllerStateMetadata = { + quz: { + persist: true, + anonymous: true, + }, +}; + +class QuzController extends BaseController< + 'QuzController', + QuzControllerState, + QuzMessenger +> { + constructor(messagingSystem: QuzMessenger) { + super({ + messenger: messagingSystem, + metadata: quzControllerStateMetadata, + name: 'QuzController', + state: { quz: 'quz' }, + }); + } + + updateQuz(quz: string) { + super.update((state) => { + state.quz = quz; + }); + } +} + // Mock BaseControllerV1 classes type BarControllerState = BaseState & { @@ -71,7 +115,7 @@ class BarController extends BaseControllerV1 { bar: 'bar', }; - override name = 'BarController'; + override name = 'BarController' as const; constructor() { super(); @@ -92,7 +136,7 @@ class BazController extends BaseControllerV1 { baz: 'baz', }; - override name = 'BazController'; + override name = 'BazController' as const; constructor() { super(); @@ -107,9 +151,13 @@ describe('ComposableController', () => { describe('BaseControllerV1', () => { it('should compose controller state', () => { + type ComposableControllerState = { + BarController: BarControllerState; + BazController: BazControllerState; + }; const composableMessenger = new ControllerMessenger< never, - ComposableControllerEvents + ComposableControllerEvents >().getRestricted({ name: 'ComposableController', allowedActions: [], @@ -127,9 +175,12 @@ describe('ComposableController', () => { }); it('should notify listeners of nested state change', () => { + type ComposableControllerState = { + BarController: BarControllerState; + }; const controllerMessenger = new ControllerMessenger< never, - ComposableControllerEvents + ComposableControllerEvents >(); const composableMessenger = controllerMessenger.getRestricted({ name: 'ComposableController', @@ -159,39 +210,60 @@ describe('ComposableController', () => { describe('BaseControllerV2', () => { it('should compose controller state', () => { + type ComposableControllerState = { + FooController: FooControllerState; + QuzController: QuzControllerState; + }; const controllerMessenger = new ControllerMessenger< never, - FooControllerEvent + | ComposableControllerEvents + | FooControllerEvent + | QuzControllerEvent >(); - const fooControllerMessenger = controllerMessenger.getRestricted({ + const fooMessenger = controllerMessenger.getRestricted< + 'FooController', + never, + QuzControllerEvent['type'] + >({ name: 'FooController', allowedActions: [], + allowedEvents: ['QuzController:stateChange'], + }); + const quzMessenger = controllerMessenger.getRestricted({ + name: 'QuzController', + allowedActions: [], allowedEvents: [], }); - const fooController = new FooController(fooControllerMessenger); + const fooController = new FooController(fooMessenger); + const quzController = new QuzController(quzMessenger); - const composableControllerMessenger = controllerMessenger.getRestricted< - 'ComposableController', - never, - FooControllerEvent['type'] - >({ + const composableControllerMessenger = controllerMessenger.getRestricted({ name: 'ComposableController', allowedActions: [], - allowedEvents: ['FooController:stateChange'], - }); - const composableController = new ComposableController({ - controllers: [fooController], - messenger: composableControllerMessenger, + allowedEvents: [ + 'FooController:stateChange', + 'QuzController:stateChange', + ], }); + const composableController = + new ComposableController({ + controllers: [fooController, quzController], + messenger: composableControllerMessenger, + }); expect(composableController.state).toStrictEqual({ FooController: { foo: 'foo' }, + QuzController: { quz: 'quz' }, }); }); it('should notify listeners of nested state change', () => { + type ComposableControllerState = { + FooController: FooControllerState; + }; const controllerMessenger = new ControllerMessenger< never, - ComposableControllerEvents | FooControllerEvent + | ComposableControllerEvents + | FooControllerEvent >(); const fooControllerMessenger = controllerMessenger.getRestricted({ name: 'FooController', @@ -199,16 +271,12 @@ describe('ComposableController', () => { allowedEvents: [], }); const fooController = new FooController(fooControllerMessenger); - const composableControllerMessenger = controllerMessenger.getRestricted< - 'ComposableController', - never, - FooControllerEvent['type'] - >({ + const composableControllerMessenger = controllerMessenger.getRestricted({ name: 'ComposableController', allowedActions: [], allowedEvents: ['FooController:stateChange'], }); - new ComposableController({ + new ComposableController({ controllers: [fooController], messenger: composableControllerMessenger, }); @@ -231,10 +299,15 @@ describe('ComposableController', () => { describe('Mixed BaseControllerV1 and BaseControllerV2', () => { it('should compose controller state', () => { + type ComposableControllerState = { + BarController: BarControllerState; + FooController: FooControllerState; + }; const barController = new BarController(); const controllerMessenger = new ControllerMessenger< never, - FooControllerEvent + | ComposableControllerEvents + | FooControllerEvent >(); const fooControllerMessenger = controllerMessenger.getRestricted({ name: 'FooController', @@ -242,19 +315,16 @@ describe('ComposableController', () => { allowedEvents: [], }); const fooController = new FooController(fooControllerMessenger); - const composableControllerMessenger = controllerMessenger.getRestricted< - 'ComposableController', - never, - FooControllerEvent['type'] - >({ + const composableControllerMessenger = controllerMessenger.getRestricted({ name: 'ComposableController', allowedActions: [], allowedEvents: ['FooController:stateChange'], }); - const composableController = new ComposableController({ - controllers: [barController, fooController], - messenger: composableControllerMessenger, - }); + const composableController = + new ComposableController({ + controllers: [barController, fooController], + messenger: composableControllerMessenger, + }); expect(composableController.state).toStrictEqual({ BarController: { bar: 'bar' }, FooController: { foo: 'foo' }, @@ -262,10 +332,15 @@ describe('ComposableController', () => { }); it('should notify listeners of BaseControllerV1 state change', () => { + type ComposableControllerState = { + BarController: BarControllerState; + FooController: FooControllerState; + }; const barController = new BarController(); const controllerMessenger = new ControllerMessenger< never, - ComposableControllerEvents | FooControllerEvent + | ComposableControllerEvents + | FooControllerEvent >(); const fooControllerMessenger = controllerMessenger.getRestricted({ name: 'FooController', @@ -273,16 +348,12 @@ describe('ComposableController', () => { allowedEvents: [], }); const fooController = new FooController(fooControllerMessenger); - const composableControllerMessenger = controllerMessenger.getRestricted< - 'ComposableController', - never, - FooControllerEvent['type'] - >({ + const composableControllerMessenger = controllerMessenger.getRestricted({ name: 'ComposableController', allowedActions: [], allowedEvents: ['FooController:stateChange'], }); - new ComposableController({ + new ComposableController({ controllers: [barController, fooController], messenger: composableControllerMessenger, }); @@ -305,10 +376,15 @@ describe('ComposableController', () => { }); it('should notify listeners of BaseControllerV2 state change', () => { + type ComposableControllerState = { + BarController: BarControllerState; + FooController: FooControllerState; + }; const barController = new BarController(); const controllerMessenger = new ControllerMessenger< never, - ComposableControllerEvents | FooControllerEvent + | ComposableControllerEvents + | FooControllerEvent >(); const fooControllerMessenger = controllerMessenger.getRestricted({ name: 'FooController', @@ -316,16 +392,12 @@ describe('ComposableController', () => { allowedEvents: [], }); const fooController = new FooController(fooControllerMessenger); - const composableControllerMessenger = controllerMessenger.getRestricted< - 'ComposableController', - never, - FooControllerEvent['type'] - >({ + const composableControllerMessenger = controllerMessenger.getRestricted({ name: 'ComposableController', allowedActions: [], allowedEvents: ['FooController:stateChange'], }); - new ComposableController({ + new ComposableController({ controllers: [barController, fooController], messenger: composableControllerMessenger, }); @@ -370,10 +442,14 @@ describe('ComposableController', () => { }); it('should throw if composing a controller that does not extend from BaseController', () => { + type ComposableControllerState = { + FooController: FooControllerState; + }; const notController = new JsonRpcEngine(); const controllerMessenger = new ControllerMessenger< never, - FooControllerEvent + | ComposableControllerEvents + | FooControllerEvent >(); const fooControllerMessenger = controllerMessenger.getRestricted({ name: 'FooController', @@ -381,11 +457,7 @@ describe('ComposableController', () => { allowedEvents: [], }); const fooController = new FooController(fooControllerMessenger); - const composableControllerMessenger = controllerMessenger.getRestricted< - 'ComposableController', - never, - FooControllerEvent['type'] - >({ + const composableControllerMessenger = controllerMessenger.getRestricted({ name: 'ComposableController', allowedActions: [], allowedEvents: ['FooController:stateChange'], diff --git a/packages/composable-controller/src/ComposableController.ts b/packages/composable-controller/src/ComposableController.ts index 8ee6bbe3a50..4c2ec8ad3bb 100644 --- a/packages/composable-controller/src/ComposableController.ts +++ b/packages/composable-controller/src/ComposableController.ts @@ -6,6 +6,8 @@ import type { EventConstraint, RestrictedControllerMessenger, StateConstraint, + StateMetadata, + ControllerStateChangeEvent, } from '@metamask/base-controller'; import type { Patch } from 'immer'; @@ -15,7 +17,7 @@ export const controllerName = 'ComposableController'; * A universal subtype of all controller instances that extend from `BaseControllerV1`. * Any `BaseControllerV1` instance can be assigned to this type. * - * Note that this type is not the greatest subtype or narrowest supertype of all `BaseControllerV1` instances. + * Note that this type is not the widest subtype or narrowest supertype of all `BaseControllerV1` instances. * This type is therefore unsuitable for general use as a type constraint, and is only intended for use within the ComposableController. */ export type BaseControllerV1Instance = @@ -27,7 +29,7 @@ export type BaseControllerV1Instance = * A universal subtype of all controller instances that extend from `BaseController` (formerly `BaseControllerV2`). * Any `BaseController` instance can be assigned to this type. * - * Note that this type is not the greatest subtype or narrowest supertype of all `BaseController` instances. + * Note that this type is not the widest subtype or narrowest supertype of all `BaseController` instances. * This type is therefore unsuitable for general use as a type constraint, and is only intended for use within the ComposableController. * * For this reason, we only look for `BaseController` properties that we use in the ComposableController (name and state). @@ -41,13 +43,25 @@ export type BaseControllerInstance = { * A universal subtype of all controller instances that extend from `BaseController` (formerly `BaseControllerV2`) or `BaseControllerV1`. * Any `BaseController` or `BaseControllerV1` instance can be assigned to this type. * - * Note that this type is not the greatest subtype or narrowest supertype of all `BaseController` and `BaseControllerV1` instances. + * Note that this type is not the widest subtype or narrowest supertype of all `BaseController` and `BaseControllerV1` instances. * This type is therefore unsuitable for general use as a type constraint, and is only intended for use within the ComposableController. */ export type ControllerInstance = | BaseControllerV1Instance | BaseControllerInstance; +/** + * The narrowest supertype of all `RestrictedControllerMessenger` instances. + */ +export type RestrictedControllerMessengerConstraint = + RestrictedControllerMessenger< + string, + ActionConstraint, + EventConstraint, + string, + string + >; + /** * Determines if the given controller is an instance of `BaseControllerV1` * @param controller - Controller instance to check @@ -82,13 +96,7 @@ export function isBaseController( ): controller is BaseController< string, StateConstraint, - RestrictedControllerMessenger< - string, - ActionConstraint, - EventConstraint, - string, - string - > + RestrictedControllerMessengerConstraint > { return ( 'name' in controller && @@ -99,43 +107,108 @@ export function isBaseController( ); } -// TODO: Replace `any` with `Json` once `BaseControllerV2` migrations are completed for all controllers. -export type ComposableControllerState = { - // `any` is used here to disable the `BaseController` type constraint which expects state properties to extend `Record`. - // `ComposableController` state needs to accommodate `BaseControllerV1` state objects that may have properties wider than `Json`. +/** + * A universal supertype for the controller state object, encompassing both `BaseControllerV1` and `BaseControllerV2` state. + */ +export type LegacyControllerStateConstraint = BaseState | StateConstraint; + +/** + * A universal supertype for the composable controller state object. + * + * This type is only intended to be used for disabling the generic constraint on the `ControllerState` type argument in the `BaseController` type as a temporary solution for ensuring compatibility with BaseControllerV1 child controllers. + * Note that it is unsuitable for general use as a type constraint. + */ +// TODO: Replace with `ComposableControllerStateConstraint` once BaseControllerV2 migrations are completed for all controllers. +type LegacyComposableControllerStateConstraint = { + // `any` is used here to disable the generic constraint on the `ControllerState` type argument in the `BaseController` type, + // enabling composable controller state types with BaseControllerV1 state objects to be. // eslint-disable-next-line @typescript-eslint/no-explicit-any [name: string]: Record; }; -export type ComposableControllerStateChangeEvent = { - type: `${typeof controllerName}:stateChange`; - payload: [ComposableControllerState, Patch[]]; +/** + * The narrowest supertype for the composable controller state object. + * This is also a widest subtype of the 'LegacyComposableControllerStateConstraint' type. + */ +// TODO: Replace with `{ [name: string]: StateConstraint }` once BaseControllerV2 migrations are completed for all controllers. +export type ComposableControllerStateConstraint = { + [name: string]: LegacyControllerStateConstraint; }; -export type ComposableControllerEvents = ComposableControllerStateChangeEvent; - -type AnyControllerStateChangeEvent = { - type: `${string}:stateChange`; - payload: [ControllerInstance['state'], Patch[]]; +/** + * A controller state change event for any controller instance that extends from either `BaseControllerV1` or `BaseControllerV2`. + */ +// TODO: Replace all instances with `ControllerStateChangeEvent` once `BaseControllerV2` migrations are completed for all controllers. +type LegacyControllerStateChangeEvent< + ControllerName extends string, + ControllerState extends LegacyControllerStateConstraint, +> = { + type: `${ControllerName}:stateChange`; + payload: [ControllerState, Patch[]]; }; -type AllowedEvents = AnyControllerStateChangeEvent; +export type ComposableControllerStateChangeEvent< + ComposableControllerState extends ComposableControllerStateConstraint, +> = LegacyControllerStateChangeEvent< + typeof controllerName, + ComposableControllerState +>; + +export type ComposableControllerEvents< + ComposableControllerState extends ComposableControllerStateConstraint, +> = ComposableControllerStateChangeEvent; + +type ChildControllerStateChangeEvents< + ComposableControllerState extends ComposableControllerStateConstraint, +> = ComposableControllerState extends Record< + infer ControllerName extends string, + infer ControllerState +> + ? ControllerState extends StateConstraint + ? ControllerStateChangeEvent + : ControllerState extends Record + ? LegacyControllerStateChangeEvent + : never + : never; + +type AllowedEvents< + ComposableControllerState extends ComposableControllerStateConstraint, +> = ChildControllerStateChangeEvents; -export type ComposableControllerMessenger = RestrictedControllerMessenger< +export type ComposableControllerMessenger< + ComposableControllerState extends ComposableControllerStateConstraint, +> = RestrictedControllerMessenger< typeof controllerName, never, - ComposableControllerEvents | AllowedEvents, + | ComposableControllerEvents + | AllowedEvents, never, - AllowedEvents['type'] + AllowedEvents['type'] >; +type GetChildControllers< + ComposableControllerState, + ControllerName extends keyof ComposableControllerState = keyof ComposableControllerState, +> = ControllerName extends string + ? ComposableControllerState[ControllerName] extends StateConstraint + ? { name: ControllerName; state: ComposableControllerState[ControllerName] } + : BaseControllerV1< + BaseConfig & Record, + BaseState & ComposableControllerState[ControllerName] + > + : never; + /** * Controller that can be used to compose multiple controllers together. + * @template ChildControllerState - The composed state of the child controllers that are being used to instantiate the composable controller. */ -export class ComposableController extends BaseController< +export class ComposableController< + ComposableControllerState extends LegacyComposableControllerStateConstraint, + ChildControllers extends ControllerInstance = GetChildControllers, +> extends BaseController< typeof controllerName, ComposableControllerState, - ComposableControllerMessenger + ComposableControllerMessenger > { /** * Creates a ComposableController instance. @@ -149,8 +222,8 @@ export class ComposableController extends BaseController< controllers, messenger, }: { - controllers: ControllerInstance[]; - messenger: ComposableControllerMessenger; + controllers: ChildControllers[]; + messenger: ComposableControllerMessenger; }) { if (messenger === undefined) { throw new Error(`Messaging system is required`); @@ -158,18 +231,21 @@ export class ComposableController extends BaseController< super({ name: controllerName, - metadata: controllers.reduce( + metadata: controllers.reduce>( (metadata, controller) => ({ ...metadata, [controller.name]: isBaseController(controller) ? controller.metadata : { persist: true, anonymous: true }, }), - {}, + {} as never, + ), + state: controllers.reduce( + (state, controller) => { + return { ...state, [controller.name]: controller.state }; + }, + {} as never, ), - state: controllers.reduce((state, controller) => { - return { ...state, [controller.name]: controller.state }; - }, {}), messenger, }); diff --git a/packages/composable-controller/src/index.ts b/packages/composable-controller/src/index.ts index 9deb15385bb..fc000563346 100644 --- a/packages/composable-controller/src/index.ts +++ b/packages/composable-controller/src/index.ts @@ -1,8 +1,10 @@ export type { - ComposableControllerState, + ComposableControllerStateConstraint, ComposableControllerStateChangeEvent, ComposableControllerEvents, ComposableControllerMessenger, + LegacyControllerStateConstraint, + RestrictedControllerMessengerConstraint, } from './ComposableController'; export { ComposableController, diff --git a/packages/message-manager/src/DecryptMessageManager.ts b/packages/message-manager/src/DecryptMessageManager.ts index 2ef29ff7380..dbfd3a4a39e 100644 --- a/packages/message-manager/src/DecryptMessageManager.ts +++ b/packages/message-manager/src/DecryptMessageManager.ts @@ -68,7 +68,7 @@ export class DecryptMessageManager extends AbstractMessageManager< /** * Name of this controller used during composition */ - override name = 'DecryptMessageManager'; + override name = 'DecryptMessageManager' as const; /** * Creates a new Message with an 'unapproved' status using the passed messageParams. diff --git a/packages/message-manager/src/EncryptionPublicKeyManager.ts b/packages/message-manager/src/EncryptionPublicKeyManager.ts index cf9288ac50e..ab4f40f7d14 100644 --- a/packages/message-manager/src/EncryptionPublicKeyManager.ts +++ b/packages/message-manager/src/EncryptionPublicKeyManager.ts @@ -65,7 +65,7 @@ export class EncryptionPublicKeyManager extends AbstractMessageManager< /** * Name of this controller used during composition */ - override name = 'EncryptionPublicKeyManager'; + override name = 'EncryptionPublicKeyManager' as const; /** * Creates a new Message with an 'unapproved' status using the passed messageParams. diff --git a/packages/message-manager/src/MessageManager.ts b/packages/message-manager/src/MessageManager.ts index 2f98cf92fc5..8a561cbfe69 100644 --- a/packages/message-manager/src/MessageManager.ts +++ b/packages/message-manager/src/MessageManager.ts @@ -70,7 +70,7 @@ export class MessageManager extends AbstractMessageManager< /** * Name of this controller used during composition */ - override name = 'MessageManager'; + override name = 'MessageManager' as const; /** * Creates a new Message with an 'unapproved' status using the passed messageParams. diff --git a/packages/message-manager/src/PersonalMessageManager.ts b/packages/message-manager/src/PersonalMessageManager.ts index 5f3db2aab47..f0f58e17baf 100644 --- a/packages/message-manager/src/PersonalMessageManager.ts +++ b/packages/message-manager/src/PersonalMessageManager.ts @@ -74,7 +74,7 @@ export class PersonalMessageManager extends AbstractMessageManager< /** * Name of this controller used during composition */ - override name = 'PersonalMessageManager'; + override name = 'PersonalMessageManager' as const; /** * Creates a new Message with an 'unapproved' status using the passed messageParams. diff --git a/packages/message-manager/src/TypedMessageManager.ts b/packages/message-manager/src/TypedMessageManager.ts index 9193d3018eb..75682dedcc3 100644 --- a/packages/message-manager/src/TypedMessageManager.ts +++ b/packages/message-manager/src/TypedMessageManager.ts @@ -95,7 +95,7 @@ export class TypedMessageManager extends AbstractMessageManager< /** * Name of this controller used during composition */ - override name = 'TypedMessageManager'; + override name = 'TypedMessageManager' as const; /** * Creates a new TypedMessage with an 'unapproved' status using the passed messageParams.