diff --git a/.changeset/polite-pens-lie.md b/.changeset/polite-pens-lie.md
new file mode 100644
index 0000000000..f07ebfc20b
--- /dev/null
+++ b/.changeset/polite-pens-lie.md
@@ -0,0 +1,5 @@
+---
+'xstate': major
+---
+
+`State` class has been removed and replaced by `MachineSnapshot` object. They largely have the same properties and methods. On of the main noticeable results of this change is that you can no longer check `state instanceof State`.
diff --git a/packages/core/src/State.ts b/packages/core/src/State.ts
index e2c368a46f..f4c97fae6b 100644
--- a/packages/core/src/State.ts
+++ b/packages/core/src/State.ts
@@ -1,13 +1,9 @@
 import isDevelopment from '#is-development';
 import { $$ACTOR_TYPE } from './interpreter.ts';
 import { memo } from './memo.ts';
-import { MachineSnapshot } from './StateMachine.ts';
 import type { StateNode } from './StateNode.ts';
-import {
-  getConfiguration,
-  getStateNodes,
-  getStateValue
-} from './stateUtils.ts';
+import type { StateMachine } from './StateMachine.ts';
+import { getStateValue } from './stateUtils.ts';
 import { TypegenDisabled, TypegenEnabled } from './typegenTypes.ts';
 import type {
   ProvidedActor,
@@ -20,11 +16,11 @@ import type {
   Prop,
   StateConfig,
   StateValue,
-  TODO,
   AnyActorRef,
   Compute,
   EventDescriptor,
-  Snapshot
+  Snapshot,
+  ParameterizedObject
 } from './types.ts';
 import { flatten, matchesState } from './utils.ts';
 
@@ -65,85 +61,70 @@ export function isStateConfig<
 }
 
 /**
- * @deprecated Use `isStateConfig(object)` or `state instanceof State` instead.
+ * @deprecated Use `isStateConfig(object)`
  */
 export const isState = isStateConfig;
-export class State<
+
+interface MachineSnapshotBase<
   TContext extends MachineContext,
   TEvent extends EventObject,
   TActor extends ProvidedActor,
   TTag extends string,
+  TOutput,
   TResolvedTypesMeta = TypegenDisabled
 > {
-  public tags: Set<string>;
+  machine: StateMachine<
+    TContext,
+    TEvent,
+    TActor,
+    ParameterizedObject,
+    ParameterizedObject,
+    string,
+    TTag,
+    unknown,
+    TOutput,
+    TResolvedTypesMeta
+  >;
+  tags: Set<string>;
+  value: StateValue;
+  status: 'active' | 'done' | 'error' | 'stopped';
+  error: unknown;
+  context: TContext;
 
-  public value: StateValue;
-  /**
-   * Indicates whether the state is a final state.
-   */
-  public status: 'active' | 'done' | 'error' | 'stopped';
-  /**
-   * The output data of the top-level finite state.
-   */
-  public error: unknown;
-  public context: TContext;
-  public historyValue: Readonly<HistoryValue<TContext, TEvent>> = {};
+  historyValue: Readonly<HistoryValue<TContext, TEvent>>;
   /**
    * The enabled state nodes representative of the state value.
    */
-  public configuration: Array<StateNode<TContext, TEvent>>;
+  configuration: Array<StateNode<TContext, TEvent>>;
   /**
    * An object mapping actor names to spawned/invoked actors.
    */
-  public children: ComputeChildren<TActor>;
+  children: ComputeChildren<TActor>;
 
   /**
-   * Creates a new `State` instance that represents the current state of a running machine.
-   *
-   * @param config
+   * The next events that will cause a transition from the current state.
    */
-  constructor(
-    config: StateConfig<TContext, TEvent>,
-    public machine: AnyStateMachine
-  ) {
-    this.context = config.context;
-    this.historyValue = config.historyValue || {};
-    this.matches = this.matches.bind(this);
-    this.configuration = config.configuration;
-    this.children = config.children as any;
-
-    this.value = getStateValue(machine.root, this.configuration);
-    this.tags = new Set(flatten(this.configuration.map((sn) => sn.tags)));
-    this.status = config.status;
-    (this as any).output = config.output;
-    (this as any).error = config.error;
-  }
+  nextEvents: Array<EventDescriptor<TEvent>>;
 
-  public toJSON() {
-    const { configuration, tags, machine, ...jsonValues } = this;
-
-    return { ...jsonValues, tags: Array.from(tags), meta: this.meta };
-  }
+  meta: Record<string, any>;
 
   /**
    * Whether the current state value is a subset of the given parent state value.
    * @param parentStateValue
    */
-  public matches<
+  matches: <
     TSV extends TResolvedTypesMeta extends TypegenEnabled
       ? Prop<Prop<TResolvedTypesMeta, 'resolved'>, 'matchesStates'>
       : StateValue
-  >(parentStateValue: TSV): boolean {
-    return matchesState(parentStateValue as any, this.value);
-  }
+  >(
+    parentStateValue: TSV
+  ) => boolean;
 
   /**
    * Whether the current state configuration has a state node with the specified `tag`.
    * @param tag
    */
-  public hasTag(tag: TTag): boolean {
-    return this.tags.has(tag as string);
-  }
+  hasTag: (tag: TTag) => boolean;
 
   /**
    * Determines whether sending the `event` will cause a non-forbidden transition
@@ -153,48 +134,219 @@ export class State<
    * @param event The event to test
    * @returns Whether the event will cause a transition
    */
-  public can(event: TEvent): boolean {
-    if (isDevelopment && !this.machine) {
-      console.warn(
-        `state.can(...) used outside of a machine-created State object; this will always return false.`
-      );
-    }
+  can: (event: TEvent) => boolean;
 
-    const transitionData = this.machine.getTransitionData(this as any, event);
+  toJSON: () => unknown;
+}
 
-    return (
-      !!transitionData?.length &&
-      // Check that at least one transition is not forbidden
-      transitionData.some((t) => t.target !== undefined || t.actions.length)
-    );
-  }
+interface ActiveMachineSnapshot<
+  TContext extends MachineContext,
+  TEvent extends EventObject,
+  TActor extends ProvidedActor,
+  TTag extends string,
+  TOutput,
+  TResolvedTypesMeta = TypegenDisabled
+> extends MachineSnapshotBase<
+    TContext,
+    TEvent,
+    TActor,
+    TTag,
+    TOutput,
+    TResolvedTypesMeta
+  > {
+  status: 'active';
+  output: undefined;
+  error: undefined;
+}
 
-  /**
-   * The next events that will cause a transition from the current state.
-   */
-  public get nextEvents(): Array<EventDescriptor<TEvent>> {
-    return memo(this, 'nextEvents', () => {
-      return [
-        ...new Set(flatten([...this.configuration.map((sn) => sn.ownEvents)]))
-      ];
-    });
-  }
+interface DoneMachineSnapshot<
+  TContext extends MachineContext,
+  TEvent extends EventObject,
+  TActor extends ProvidedActor,
+  TTag extends string,
+  TOutput,
+  TResolvedTypesMeta = TypegenDisabled
+> extends MachineSnapshotBase<
+    TContext,
+    TEvent,
+    TActor,
+    TTag,
+    TOutput,
+    TResolvedTypesMeta
+  > {
+  status: 'done';
+  output: TOutput;
+  error: undefined;
+}
+
+interface ErrorMachineSnapshot<
+  TContext extends MachineContext,
+  TEvent extends EventObject,
+  TActor extends ProvidedActor,
+  TTag extends string,
+  TOutput,
+  TResolvedTypesMeta = TypegenDisabled
+> extends MachineSnapshotBase<
+    TContext,
+    TEvent,
+    TActor,
+    TTag,
+    TOutput,
+    TResolvedTypesMeta
+  > {
+  status: 'error';
+  output: undefined;
+  error: unknown;
+}
 
-  public get meta(): Record<string, any> {
-    return this.configuration.reduce((acc, stateNode) => {
-      if (stateNode.meta !== undefined) {
-        acc[stateNode.id] = stateNode.meta;
+interface StoppedMachineSnapshot<
+  TContext extends MachineContext,
+  TEvent extends EventObject,
+  TActor extends ProvidedActor,
+  TTag extends string,
+  TOutput,
+  TResolvedTypesMeta = TypegenDisabled
+> extends MachineSnapshotBase<
+    TContext,
+    TEvent,
+    TActor,
+    TTag,
+    TOutput,
+    TResolvedTypesMeta
+  > {
+  status: 'stopped';
+  output: undefined;
+  error: undefined;
+}
+
+export type MachineSnapshot<
+  TContext extends MachineContext,
+  TEvent extends EventObject,
+  TActor extends ProvidedActor,
+  TTag extends string,
+  TOutput,
+  TResolvedTypesMeta = TypegenDisabled
+> =
+  | ActiveMachineSnapshot<
+      TContext,
+      TEvent,
+      TActor,
+      TTag,
+      TOutput,
+      TResolvedTypesMeta
+    >
+  | DoneMachineSnapshot<
+      TContext,
+      TEvent,
+      TActor,
+      TTag,
+      TOutput,
+      TResolvedTypesMeta
+    >
+  | ErrorMachineSnapshot<
+      TContext,
+      TEvent,
+      TActor,
+      TTag,
+      TOutput,
+      TResolvedTypesMeta
+    >
+  | StoppedMachineSnapshot<
+      TContext,
+      TEvent,
+      TActor,
+      TTag,
+      TOutput,
+      TResolvedTypesMeta
+    >;
+
+export function createMachineSnapshot<
+  TContext extends MachineContext,
+  TEvent extends EventObject,
+  TActor extends ProvidedActor,
+  TTag extends string,
+  TResolvedTypesMeta = TypegenDisabled
+>(
+  config: StateConfig<TContext, TEvent>,
+  machine: AnyStateMachine
+): MachineSnapshot<
+  TContext,
+  TEvent,
+  TActor,
+  TTag,
+  undefined,
+  TResolvedTypesMeta
+> {
+  return {
+    status: config.status as any,
+    output: config.output,
+    error: config.error,
+    machine,
+    context: config.context,
+    configuration: config.configuration,
+    value: getStateValue(machine.root, config.configuration),
+    tags: new Set(flatten(config.configuration.map((sn) => sn.tags))),
+    children: config.children as any,
+    historyValue: config.historyValue || {},
+    matches(parentStateValue) {
+      return matchesState(parentStateValue as any, this.value);
+    },
+    hasTag(tag) {
+      return this.tags.has(tag);
+    },
+    can(event) {
+      if (isDevelopment && !this.machine) {
+        console.warn(
+          `state.can(...) used outside of a machine-created State object; this will always return false.`
+        );
       }
-      return acc;
-    }, {} as Record<string, any>);
-  }
+
+      const transitionData = this.machine.getTransitionData(this as any, event);
+
+      return (
+        !!transitionData?.length &&
+        // Check that at least one transition is not forbidden
+        transitionData.some((t) => t.target !== undefined || t.actions.length)
+      );
+    },
+    get nextEvents() {
+      return memo(this, 'nextEvents', () => {
+        return [
+          ...new Set(flatten([...this.configuration.map((sn) => sn.ownEvents)]))
+        ];
+      });
+    },
+    get meta() {
+      return this.configuration.reduce((acc, stateNode) => {
+        if (stateNode.meta !== undefined) {
+          acc[stateNode.id] = stateNode.meta;
+        }
+        return acc;
+      }, {} as Record<string, any>);
+    },
+    toJSON() {
+      const {
+        configuration,
+        tags,
+        machine,
+        nextEvents,
+        toJSON,
+        can,
+        hasTag,
+        matches,
+        ...jsonValues
+      } = this;
+      return { ...jsonValues, tags: Array.from(tags) };
+    }
+  };
 }
 
-export function cloneState<TState extends AnyState>(
+export function cloneMachineSnapshot<TState extends AnyState>(
   state: TState,
   config: Partial<StateConfig<any, any>> = {}
 ): TState {
-  return new State(
+  return createMachineSnapshot(
+    // TODO: it's wasteful that this spread triggers getters
     { ...state, ...config } as StateConfig<any, any>,
     state.machine
   ) as TState;
@@ -218,8 +370,19 @@ export function getPersistedState<
   >,
   options?: unknown
 ): Snapshot<unknown> {
-  const { configuration, tags, machine, children, context, ...jsonValues } =
-    state;
+  const {
+    configuration,
+    tags,
+    machine,
+    children,
+    context,
+    can,
+    hasTag,
+    matches,
+    toJSON,
+    nextEvents,
+    ...jsonValues
+  } = state;
 
   const childrenJson: Record<string, unknown> = {};
 
diff --git a/packages/core/src/StateMachine.ts b/packages/core/src/StateMachine.ts
index c648746f66..c1560c3573 100644
--- a/packages/core/src/StateMachine.ts
+++ b/packages/core/src/StateMachine.ts
@@ -1,7 +1,12 @@
 import { assign } from './actions.ts';
 import { createInitEvent } from './eventUtils.ts';
 import { STATE_DELIMITER } from './constants.ts';
-import { cloneState, getPersistedState, State } from './State.ts';
+import {
+  cloneMachineSnapshot,
+  createMachineSnapshot,
+  getPersistedState,
+  MachineSnapshot
+} from './State.ts';
 import { StateNode } from './StateNode.ts';
 import {
   getConfiguration,
@@ -32,7 +37,6 @@ import type {
   MachineImplementationsSimplified,
   MachineTypes,
   NoInfer,
-  StateConfig,
   StateMachineDefinition,
   StateValue,
   TransitionDefinition,
@@ -55,35 +59,6 @@ import isDevelopment from '#is-development';
 export const STATE_IDENTIFIER = '#';
 export const WILDCARD = '*';
 
-export type MachineSnapshot<
-  TContext extends MachineContext,
-  TEvent extends EventObject,
-  TActor extends ProvidedActor,
-  TTag extends string,
-  TOutput,
-  TResolvedTypesMeta = TypegenDisabled
-> =
-  | (State<TContext, TEvent, TActor, TTag, TResolvedTypesMeta> & {
-      status: 'active';
-      output: undefined;
-      error: undefined;
-    })
-  | (State<TContext, TEvent, TActor, TTag, TResolvedTypesMeta> & {
-      status: 'done';
-      output: TOutput;
-      error: undefined;
-    })
-  | (State<TContext, TEvent, TActor, TTag, TResolvedTypesMeta> & {
-      status: 'error';
-      output: undefined;
-      error: unknown;
-    })
-  | (State<TContext, TEvent, TActor, TTag, TResolvedTypesMeta> & {
-      status: 'stopped';
-      output: undefined;
-      error: undefined;
-    });
-
 export class StateMachine<
   TContext extends MachineContext,
   TEvent extends EventObject,
@@ -272,7 +247,7 @@ export class StateMachine<
       getStateNodes(this.root, resolvedStateValue)
     );
 
-    return new State(
+    return createMachineSnapshot(
       {
         configuration: [...configurationSet],
         context: config.context || ({} as TContext),
@@ -326,7 +301,7 @@ export class StateMachine<
       isErrorActorEvent(event) &&
       !state.nextEvents.some((nextEvent) => nextEvent === event.type)
     ) {
-      return cloneState(state, {
+      return cloneMachineSnapshot(state, {
         status: 'error',
         error: event.data
       });
@@ -393,7 +368,7 @@ export class StateMachine<
   > {
     const { context } = this.config;
 
-    const preInitial = new State(
+    const preInitial = createMachineSnapshot(
       {
         context:
           typeof context !== 'function' && context ? context : ({} as TContext),
@@ -592,7 +567,7 @@ export class StateMachine<
       children[actorId] = actorRef;
     });
 
-    const restoredSnapshot = new State(
+    const restoredSnapshot = createMachineSnapshot(
       {
         ...(snapshot as any),
         children,
diff --git a/packages/core/src/StateNode.ts b/packages/core/src/StateNode.ts
index a5c950a25e..9d76b56e04 100644
--- a/packages/core/src/StateNode.ts
+++ b/packages/core/src/StateNode.ts
@@ -1,4 +1,4 @@
-import type { State } from './State.ts';
+import { MachineSnapshot } from './State.ts';
 import type { StateMachine } from './StateMachine.ts';
 import { NULL_EVENT, STATE_DELIMITER } from './constants.ts';
 import { evaluateGuard } from './guards.ts';
@@ -362,7 +362,7 @@ export class StateNode<
   }
 
   public next(
-    state: State<TContext, TEvent, TODO, TODO, TODO>,
+    state: MachineSnapshot<TContext, TEvent, any, any, any, any>,
     event: TEvent
   ): TransitionDefinition<TContext, TEvent>[] | undefined {
     const eventType = event.type;
diff --git a/packages/core/src/actions/assign.ts b/packages/core/src/actions/assign.ts
index c8e894b256..8f771f50e5 100644
--- a/packages/core/src/actions/assign.ts
+++ b/packages/core/src/actions/assign.ts
@@ -1,5 +1,5 @@
 import isDevelopment from '#is-development';
-import { cloneState } from '../State.ts';
+import { cloneMachineSnapshot } from '../State.ts';
 import { Spawner, createSpawner } from '../spawn.ts';
 import type {
   ActionArgs,
@@ -68,7 +68,7 @@ function resolveAssign(
   const updatedContext = Object.assign({}, state.context, partialUpdate);
 
   return [
-    cloneState(state, {
+    cloneMachineSnapshot(state, {
       context: updatedContext,
       children: Object.keys(spawnedChildren).length
         ? {
diff --git a/packages/core/src/actions/spawn.ts b/packages/core/src/actions/spawn.ts
index 5957356f61..0a7fee88eb 100644
--- a/packages/core/src/actions/spawn.ts
+++ b/packages/core/src/actions/spawn.ts
@@ -1,5 +1,5 @@
 import isDevelopment from '#is-development';
-import { cloneState } from '../State.ts';
+import { cloneMachineSnapshot } from '../State.ts';
 import { createErrorActorEvent } from '../eventUtils.ts';
 import { ProcessingStatus, createActor } from '../interpreter.ts';
 import {
@@ -93,7 +93,7 @@ function resolveSpawn(
     );
   }
   return [
-    cloneState(state, {
+    cloneMachineSnapshot(state, {
       children: {
         ...state.children,
         [resolvedId]: actorRef!
diff --git a/packages/core/src/actions/stop.ts b/packages/core/src/actions/stop.ts
index 621896c23f..6119d6b7e8 100644
--- a/packages/core/src/actions/stop.ts
+++ b/packages/core/src/actions/stop.ts
@@ -1,5 +1,5 @@
 import isDevelopment from '#is-development';
-import { cloneState } from '../State.ts';
+import { cloneMachineSnapshot } from '../State.ts';
 import { ProcessingStatus } from '../interpreter.ts';
 import {
   ActionArgs,
@@ -44,7 +44,7 @@ function resolveStop(
     delete children[resolvedActorRef.id];
   }
   return [
-    cloneState(state, {
+    cloneMachineSnapshot(state, {
       children
     }),
     resolvedActorRef
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index f535d1b9d0..4fec3d1687 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -2,7 +2,7 @@ export * from './actions.ts';
 export * from './actors/index.ts';
 export { SimulatedClock } from './SimulatedClock.ts';
 export { type Spawner } from './spawn.ts';
-export { StateMachine, type MachineSnapshot } from './StateMachine.ts';
+export { StateMachine } from './StateMachine.ts';
 export { getStateNodes } from './stateUtils.ts';
 export * from './typegenTypes.ts';
 export * from './types.ts';
@@ -10,7 +10,7 @@ export { waitFor } from './waitFor.ts';
 import { Actor, createActor, interpret, Interpreter } from './interpreter.ts';
 import { createMachine } from './Machine.ts';
 import { mapState } from './mapState.ts';
-import { State } from './State.ts';
+export { type MachineSnapshot } from './State.ts';
 import { StateNode } from './StateNode.ts';
 // TODO: decide from where those should be exported
 export { matchesState, pathToStateValue, toObserver } from './utils.ts';
@@ -20,7 +20,6 @@ export {
   createMachine,
   interpret,
   mapState,
-  State,
   StateNode,
   type Interpreter
 };
diff --git a/packages/core/src/stateUtils.ts b/packages/core/src/stateUtils.ts
index f23144bcaf..c2b2ec3573 100644
--- a/packages/core/src/stateUtils.ts
+++ b/packages/core/src/stateUtils.ts
@@ -1,5 +1,5 @@
 import isDevelopment from '#is-development';
-import { State, cloneState } from './State.ts';
+import { MachineSnapshot, cloneMachineSnapshot } from './State.ts';
 import type { StateNode } from './StateNode.ts';
 import { raise } from './actions.ts';
 import { createAfterEvent, createDoneStateEvent } from './eventUtils.ts';
@@ -634,17 +634,12 @@ export function getStateNodeByPath(
 /**
  * Returns the state nodes represented by the current state value.
  *
- * @param state The state value or State instance
+ * @param stateValue The state value or State instance
  */
 export function getStateNodes<
   TContext extends MachineContext,
   TEvent extends EventObject
->(
-  stateNode: AnyStateNode,
-  state: StateValue | State<TContext, TEvent, TODO, TODO, TODO>
-): Array<AnyStateNode> {
-  const stateValue = state instanceof State ? state.value : toStateValue(state);
-
+>(stateNode: AnyStateNode, stateValue: StateValue): Array<AnyStateNode> {
   if (typeof stateValue === 'string') {
     return [stateNode, stateNode.states[stateValue]];
   }
@@ -677,7 +672,7 @@ export function transitionAtomicNode<
 >(
   stateNode: AnyStateNode,
   stateValue: string,
-  state: State<TContext, TEvent, TODO, TODO, TODO>,
+  state: MachineSnapshot<TContext, TEvent, any, any, any, any>,
   event: TEvent
 ): Array<TransitionDefinition<TContext, TEvent>> | undefined {
   const childStateNode = getStateNode(stateNode, stateValue);
@@ -696,7 +691,7 @@ export function transitionCompoundNode<
 >(
   stateNode: AnyStateNode,
   stateValue: StateValueMap,
-  state: State<TContext, TEvent, TODO, TODO, TODO>,
+  state: MachineSnapshot<TContext, TEvent, any, any, any, any>,
   event: TEvent
 ): Array<TransitionDefinition<TContext, TEvent>> | undefined {
   const subStateKeys = Object.keys(stateValue);
@@ -722,7 +717,7 @@ export function transitionParallelNode<
 >(
   stateNode: AnyStateNode,
   stateValue: StateValueMap,
-  state: State<TContext, TEvent, TODO, TODO, TODO>,
+  state: MachineSnapshot<TContext, TEvent, any, any, any, any>,
   event: TEvent
 ): Array<TransitionDefinition<TContext, TEvent>> | undefined {
   const allInnerTransitions: Array<TransitionDefinition<TContext, TEvent>> = [];
@@ -758,13 +753,7 @@ export function transitionNode<
 >(
   stateNode: AnyStateNode,
   stateValue: StateValue,
-  state: State<
-    TContext,
-    TEvent,
-    TODO,
-    TODO,
-    TODO // tags
-  >,
+  state: MachineSnapshot<TContext, TEvent, any, any, any, any>,
   event: TEvent
 ): Array<TransitionDefinition<TContext, TEvent>> | undefined {
   // leaf node
@@ -1065,7 +1054,7 @@ export function microstep<
     ) {
       return nextState;
     }
-    return cloneState(nextState, {
+    return cloneMachineSnapshot(nextState, {
       configuration: nextConfiguration,
       historyValue
     });
@@ -1203,7 +1192,7 @@ function enterStates(
         continue;
       }
 
-      nextState = cloneState(nextState, {
+      nextState = cloneMachineSnapshot(nextState, {
         status: 'done',
         output: getMachineOutput(
           nextState,
@@ -1634,9 +1623,12 @@ export function macrostep(
 
   // Handle stop event
   if (event.type === XSTATE_STOP) {
-    nextState = cloneState(stopChildren(nextState, event, actorScope), {
-      status: 'stopped'
-    });
+    nextState = cloneMachineSnapshot(
+      stopChildren(nextState, event, actorScope),
+      {
+        status: 'stopped'
+      }
+    );
     states.push(nextState);
 
     return {
diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts
index 2ae4a39ec1..bc920d99c5 100644
--- a/packages/core/src/types.ts
+++ b/packages/core/src/types.ts
@@ -1,7 +1,7 @@
 import type { StateNode } from './StateNode.ts';
-import type { State } from './State.ts';
+import type { MachineSnapshot } from './State.ts';
 import type { Clock, Actor, ProcessingStatus } from './interpreter.ts';
-import type { MachineSnapshot, StateMachine } from './StateMachine.ts';
+import type { StateMachine } from './StateMachine.ts';
 import {
   TypegenDisabled,
   ResolveTypegenMeta,
@@ -926,13 +926,8 @@ export type AnyStateNode = StateNode<any, any>;
 
 export type AnyStateNodeDefinition = StateNodeDefinition<any, any>;
 
-export type AnyState = State<
-  any, // context
-  any, // event
-  any, // actor
-  any, // tags
-  any // typegen
->;
+// TODO: replace with AnyMachineSnapshot
+export type AnyState = MachineSnapshot<any, any, any, any, any, any>;
 
 export type AnyStateMachine = StateMachine<
   any,
@@ -2139,10 +2134,11 @@ type ResolveEventType<T> = ReturnTypeOrValue<T> extends infer R
       infer _TResolvedTypesMeta
     >
     ? TEvent
-    : R extends State<
+    : R extends MachineSnapshot<
         infer _TContext,
         infer TEvent,
         infer _TActor,
+        infer _TTag,
         infer _TOutput,
         infer _TResolvedTypesMeta
       >
@@ -2172,10 +2168,11 @@ export type ContextFrom<T> = ReturnTypeOrValue<T> extends infer R
       infer _TTypesMeta
     >
     ? TContext
-    : R extends State<
+    : R extends MachineSnapshot<
         infer TContext,
         infer _TEvent,
         infer _TActor,
+        infer _TTag,
         infer _TOutput,
         infer _TResolvedTypesMeta
       >
diff --git a/packages/core/test/interpreter.test.ts b/packages/core/test/interpreter.test.ts
index 0538e8c7aa..c5da52e7fd 100644
--- a/packages/core/test/interpreter.test.ts
+++ b/packages/core/test/interpreter.test.ts
@@ -12,7 +12,6 @@ import {
   stop,
   log
 } from '../src/index.ts';
-import { State } from '../src/State';
 import { isObservable } from '../src/utils';
 import { interval, from } from 'rxjs';
 import { fromObservable } from '../src/actors/observable';
diff --git a/packages/core/test/machine.test.ts b/packages/core/test/machine.test.ts
index 81fc43bb6b..d87e98fc39 100644
--- a/packages/core/test/machine.test.ts
+++ b/packages/core/test/machine.test.ts
@@ -1,5 +1,4 @@
 import { createActor, createMachine, assign } from '../src/index.ts';
-import { State } from '../src/State.ts';
 
 const pedestrianStates = {
   initial: 'walk',
diff --git a/packages/core/test/scxml.test.ts b/packages/core/test/scxml.test.ts
index cc15e00e44..ae6090d7fc 100644
--- a/packages/core/test/scxml.test.ts
+++ b/packages/core/test/scxml.test.ts
@@ -422,7 +422,7 @@ async function runTestToCompletion(
     }
     service.send({ type: event.name });
 
-    const stateIds = getStateNodes(machine.root, nextState).map(
+    const stateIds = getStateNodes(machine.root, nextState.value).map(
       (stateNode) => stateNode.id
     );
 
diff --git a/packages/core/test/state.test.ts b/packages/core/test/state.test.ts
index 69b6fd6a66..aed7e61913 100644
--- a/packages/core/test/state.test.ts
+++ b/packages/core/test/state.test.ts
@@ -176,14 +176,6 @@ describe('State', () => {
     });
   });
 
-  describe('State.prototype.matches', () => {
-    it('should keep reference to state instance after destructuring', () => {
-      const { matches } = createActor(exampleMachine).getSnapshot();
-
-      expect(matches('one')).toBe(true);
-    });
-  });
-
   describe('status', () => {
     it('should show that a machine has not reached its final state', () => {
       expect(createActor(exampleMachine).getSnapshot().status).not.toBe('done');
diff --git a/packages/core/test/tags.test.ts b/packages/core/test/tags.test.ts
index d66b4e80af..34b75d181e 100644
--- a/packages/core/test/tags.test.ts
+++ b/packages/core/test/tags.test.ts
@@ -143,6 +143,6 @@ describe('tags', () => {
 
     const jsonState = createActor(machine).getSnapshot().toJSON();
 
-    expect(jsonState.tags).toEqual(['go', 'light']);
+    expect((jsonState as any).tags).toEqual(['go', 'light']);
   });
 });
diff --git a/packages/xstate-graph/test/graph.test.ts b/packages/xstate-graph/test/graph.test.ts
index 4c0f6d07d5..8c3ecbc2df 100644
--- a/packages/xstate-graph/test/graph.test.ts
+++ b/packages/xstate-graph/test/graph.test.ts
@@ -3,7 +3,6 @@ import {
   createMachine,
   EventObject,
   assign,
-  State,
   fromTransition,
   Snapshot
 } from 'xstate';
@@ -30,14 +29,14 @@ function getPathSnapshot(path: StatePath<Snapshot<unknown>, any>): {
 } {
   return {
     state:
-      path.state instanceof State
+      'machine' in path.state && 'value' in path.state
         ? path.state.value
         : 'context' in path.state
         ? path.state.context
         : path.state,
     steps: path.steps.map((step) => ({
       state:
-        step.state instanceof State
+        'machine' in step.state && 'value' in step.state
           ? step.state.value
           : 'context' in step.state
           ? step.state.context
diff --git a/packages/xstate-inspect/src/serialize.ts b/packages/xstate-inspect/src/serialize.ts
index 3bae20417a..80aaee723f 100644
--- a/packages/xstate-inspect/src/serialize.ts
+++ b/packages/xstate-inspect/src/serialize.ts
@@ -21,7 +21,7 @@ export function selectivelyStringify<T extends object>(
 }
 
 export function stringifyState(state: AnyState, replacer?: Replacer): string {
-  const { machine, configuration, tags, ...stateToStringify } = state;
+  const { machine, configuration, tags, meta, ...stateToStringify } = state;
   return selectivelyStringify(
     { ...stateToStringify, tags: Array.from(tags) },
     ['context'],
diff --git a/packages/xstate-inspect/test/inspect.test.ts b/packages/xstate-inspect/test/inspect.test.ts
index 67845843cd..5bebc7191f 100644
--- a/packages/xstate-inspect/test/inspect.test.ts
+++ b/packages/xstate-inspect/test/inspect.test.ts
@@ -97,7 +97,7 @@ describe('@xstate/inspect', () => {
           "machine": "{"id":"whatever","key":"whatever","type":"compound","initial":{"target":["#whatever.active"],"source":"#whatever","actions":[],"eventType":null},"history":false,"states":{"active":{"id":"whatever.active","key":"active","type":"atomic","initial":{"target":[],"source":"#whatever.active","actions":[],"eventType":null},"history":false,"states":{},"on":{},"transitions":[],"entry":[],"exit":[],"order":1,"invoke":[],"tags":[]}},"on":{},"transitions":[],"entry":[],"exit":[],"order":-1,"invoke":[],"tags":[]}",
           "parent": undefined,
           "sessionId": "x:1",
-          "state": "{"value":"active","status":"active","context":{"cycle":"[Circular]"},"historyValue":{},"children":{},"tags":[]}",
+          "state": "{"status":"active","context":{"cycle":"[Circular]"},"value":"active","children":{},"historyValue":{},"tags":[]}",
           "type": "service.register",
         },
       ]
@@ -148,7 +148,7 @@ describe('@xstate/inspect', () => {
         },
         {
           "sessionId": "x:3",
-          "state": "{"value":"active","status":"active","context":{},"historyValue":{},"children":{},"tags":[]}",
+          "state": "{"status":"active","context":{},"value":"active","children":{},"historyValue":{},"tags":[]}",
           "type": "service.state",
         },
       ]
@@ -205,7 +205,7 @@ describe('@xstate/inspect', () => {
           "machine": "{"id":"(machine)","key":"(machine)","type":"compound","initial":{"target":["#(machine).active"],"source":"#(machine)","actions":[],"eventType":null},"history":false,"states":{"active":{"id":"(machine).active","key":"active","type":"atomic","initial":{"target":[],"source":"#(machine).active","actions":[],"eventType":null},"history":false,"states":{},"on":{},"transitions":[],"entry":[],"exit":[],"order":1,"invoke":[],"tags":[]}},"on":{},"transitions":[],"entry":[],"exit":[],"order":-1,"invoke":[],"tags":[]}",
           "parent": undefined,
           "sessionId": "x:5",
-          "state": "{"value":"active","status":"active","context":{"map":"map","deep":{"map":"map"}},"historyValue":{},"children":{},"tags":[]}",
+          "state": "{"status":"active","context":{"map":"map","deep":{"map":"map"}},"value":"active","children":{},"historyValue":{},"tags":[]}",
           "type": "service.register",
         },
         {
@@ -215,7 +215,7 @@ describe('@xstate/inspect', () => {
         },
         {
           "sessionId": "x:5",
-          "state": "{"value":"active","status":"active","context":{"map":"map","deep":{"map":"map"}},"historyValue":{},"children":{},"tags":[]}",
+          "state": "{"status":"active","context":{"map":"map","deep":{"map":"map"}},"value":"active","children":{},"historyValue":{},"tags":[]}",
           "type": "service.state",
         },
       ]
@@ -324,7 +324,7 @@ describe('@xstate/inspect', () => {
         },
         {
           "sessionId": "x:7",
-          "state": "{"value":{},"status":"active","context":{"value":{"unsafe":"[unsafe]"}},"historyValue":{},"children":{},"tags":[]}",
+          "state": "{"status":"active","context":{"value":{"unsafe":"[unsafe]"}},"value":{},"children":{},"historyValue":{},"tags":[]}",
           "type": "service.state",
         },
       ]
@@ -346,7 +346,7 @@ describe('@xstate/inspect', () => {
         },
         {
           "sessionId": "x:7",
-          "state": "{"value":{},"status":"active","context":{"value":{"unsafe":"[unsafe]"}},"historyValue":{},"children":{},"tags":[]}",
+          "state": "{"status":"active","context":{"value":{"unsafe":"[unsafe]"}},"value":{},"children":{},"historyValue":{},"tags":[]}",
           "type": "service.state",
         },
       ]
diff --git a/packages/xstate-solid/src/deriveServiceState.ts b/packages/xstate-solid/src/deriveServiceState.ts
index c97feeddfb..32c6dc035f 100644
--- a/packages/xstate-solid/src/deriveServiceState.ts
+++ b/packages/xstate-solid/src/deriveServiceState.ts
@@ -1,5 +1,4 @@
-import { AnyState, matchesState } from 'xstate';
-import type { CheckSnapshot } from './types.ts';
+import { AnyState, Snapshot } from 'xstate';
 
 function isState(state: any): state is AnyState {
   return (
@@ -12,34 +11,38 @@ function isState(state: any): state is AnyState {
   );
 }
 
+function reactiveMethod<T, Args extends unknown[], R>(
+  method: (this: T, ...args: Args) => R
+) {
+  return function (this: T, ...args: Args) {
+    return method.apply(this, args);
+  };
+}
+
 /**
  * Takes in an interpreter or actor ref and returns a State object with reactive
  * methods or if not State, the initial value passed in
  * @param state {AnyState | unknown}
  * @param prevState {AnyState | unknown}
  */
-export const deriveServiceState = <
-  StateSnapshot extends AnyState,
-  StateReturnType = CheckSnapshot<StateSnapshot>
->(
-  state: StateSnapshot | unknown,
-  prevState?: StateSnapshot | unknown
-): StateReturnType => {
+export const deriveServiceState = <T extends unknown>(
+  state: Snapshot<T>,
+  prevState?: Snapshot<T>
+) => {
   if (isState(state)) {
+    const shouldKeepReactiveMethods = prevState && isState(prevState);
     return {
       ...state,
-      toJSON: state.toJSON,
-      can: state.can,
-      hasTag: state.hasTag,
-      nextEvents: state.nextEvents,
-      matches:
-        prevState && isState(prevState)
-          ? prevState.matches
-          : function (this: AnyState, parentStateValue: string) {
-              return matchesState(parentStateValue, this.value);
-            }
-    } as StateReturnType;
-  } else {
-    return state as StateReturnType;
+      can: shouldKeepReactiveMethods
+        ? prevState.can
+        : reactiveMethod(state.can),
+      hasTag: shouldKeepReactiveMethods
+        ? prevState.hasTag
+        : reactiveMethod(state.hasTag),
+      matches: shouldKeepReactiveMethods
+        ? prevState.matches
+        : reactiveMethod(state.matches)
+    };
   }
+  return state;
 };
diff --git a/packages/xstate-solid/src/types.ts b/packages/xstate-solid/src/types.ts
index a8721fe0f8..3c79178987 100644
--- a/packages/xstate-solid/src/types.ts
+++ b/packages/xstate-solid/src/types.ts
@@ -1,56 +1,10 @@
 import type {
-  AnyState,
   AnyStateMachine,
   AreAllImplementationsAssumedToBeProvided,
-  EventObject,
   InternalMachineImplementations,
-  ActorOptions,
-  MachineContext,
-  ProvidedActor,
-  TypegenDisabled,
-  HomomorphicPick,
-  MachineSnapshot
+  ActorOptions
 } from 'xstate';
 
-type MachineSnapshotPOJO<
-  TContext extends MachineContext,
-  TEvent extends EventObject = EventObject,
-  TActor extends ProvidedActor = ProvidedActor,
-  TTag extends string = string,
-  TOutput = unknown,
-  TResolvedTypesMeta = TypegenDisabled
-> = HomomorphicPick<
-  MachineSnapshot<TContext, TEvent, TActor, TTag, TOutput, TResolvedTypesMeta>,
-  keyof MachineSnapshot<
-    TContext,
-    TEvent,
-    TActor,
-    TTag,
-    TOutput,
-    TResolvedTypesMeta
-  >
->;
-
-// Converts a State class type to a POJO State type. This reflects that the state
-// is being spread into a new object for reactive tracking in SolidJS
-export type CheckSnapshot<Snapshot> = Snapshot extends MachineSnapshot<
-  infer TContext,
-  infer TEvents,
-  infer TActor,
-  infer TTag,
-  infer TOutput,
-  infer TResolvedTypesMeta
->
-  ? MachineSnapshotPOJO<
-      TContext,
-      TEvents,
-      TActor,
-      TTag,
-      TOutput,
-      TResolvedTypesMeta
-    >
-  : Snapshot;
-
 type InternalMachineOpts<
   TMachine extends AnyStateMachine,
   RequireMissing extends boolean = false
diff --git a/packages/xstate-solid/src/useActor.ts b/packages/xstate-solid/src/useActor.ts
index 1915e9b6aa..c423bb3c3c 100644
--- a/packages/xstate-solid/src/useActor.ts
+++ b/packages/xstate-solid/src/useActor.ts
@@ -3,7 +3,6 @@ import type { Accessor } from 'solid-js';
 import { createEffect, createMemo, onCleanup } from 'solid-js';
 import { deriveServiceState } from './deriveServiceState.ts';
 import { createImmutable } from './createImmutable.ts';
-import type { CheckSnapshot } from './types.ts';
 import { unwrap } from 'solid-js/store';
 
 const noop = () => {
@@ -14,13 +13,13 @@ type Sender<TEvent> = (event: TEvent) => void;
 
 export function useActor<TActor extends ActorRef<any, any>>(
   actorRef: Accessor<TActor> | TActor
-): [Accessor<CheckSnapshot<SnapshotFrom<TActor>>>, TActor['send']];
+): [Accessor<SnapshotFrom<TActor>>, TActor['send']];
 export function useActor<
   TSnapshot extends Snapshot<unknown>,
   TEvent extends EventObject
 >(
   actorRef: Accessor<ActorRef<TEvent, TSnapshot>> | ActorRef<TEvent, TSnapshot>
-): [Accessor<CheckSnapshot<TSnapshot>>, Sender<TEvent>];
+): [Accessor<TSnapshot>, Sender<TEvent>];
 export function useActor(
   actorRef:
     | Accessor<ActorRef<EventObject, Snapshot<unknown>>>
@@ -34,7 +33,10 @@ export function useActor(
     snapshot: deriveServiceState(actorMemo().getSnapshot?.())
   });
 
-  const setActorState = (actorState: unknown, prevState?: unknown) => {
+  const setActorState = (
+    actorState: Snapshot<unknown>,
+    prevState?: Snapshot<unknown>
+  ) => {
     setState({
       snapshot: deriveServiceState(actorState, prevState)
     });
diff --git a/packages/xstate-solid/src/useMachine.ts b/packages/xstate-solid/src/useMachine.ts
index db8aeb7f58..6c997542c4 100644
--- a/packages/xstate-solid/src/useMachine.ts
+++ b/packages/xstate-solid/src/useMachine.ts
@@ -1,5 +1,5 @@
-import type { AnyStateMachine, StateFrom, Actor, Prop } from 'xstate';
-import type { CheckSnapshot, RestParams } from './types.ts';
+import type { AnyStateMachine, Actor, Prop, SnapshotFrom } from 'xstate';
+import type { RestParams } from './types.ts';
 import { createService } from './createService.ts';
 import { onCleanup, onMount } from 'solid-js';
 import { deriveServiceState } from './deriveServiceState.ts';
@@ -9,11 +9,7 @@ import { unwrap } from 'solid-js/store';
 type UseMachineReturn<
   TMachine extends AnyStateMachine,
   TInterpreter = Actor<TMachine>
-> = [
-  CheckSnapshot<StateFrom<TMachine>>,
-  Prop<TInterpreter, 'send'>,
-  TInterpreter
-];
+> = [SnapshotFrom<TMachine>, Prop<TInterpreter, 'send'>, TInterpreter];
 
 export function useMachine<TMachine extends AnyStateMachine>(
   machine: TMachine,
@@ -28,7 +24,7 @@ export function useMachine<TMachine extends AnyStateMachine>(
   onMount(() => {
     const { unsubscribe } = service.subscribe((nextState) => {
       setState(
-        deriveServiceState(nextState, unwrap(state)) as StateFrom<TMachine>
+        deriveServiceState(nextState, unwrap(state)) as SnapshotFrom<TMachine>
       );
     });
 
diff --git a/packages/xstate-solid/test/useActor.test.tsx b/packages/xstate-solid/test/useActor.test.tsx
index 1468954bfa..86de7b86ef 100644
--- a/packages/xstate-solid/test/useActor.test.tsx
+++ b/packages/xstate-solid/test/useActor.test.tsx
@@ -374,7 +374,7 @@ describe('useActor', () => {
             data-testid="transition-button"
             onclick={() => send({ type: 'TRANSITION' })}
           />
-          <div data-testid="to-json">{toJson().value.toString()}</div>
+          <div data-testid="to-json">{(toJson() as any).value.toString()}</div>
         </div>
       );
     };
diff --git a/packages/xstate-solid/test/useMachine.test.tsx b/packages/xstate-solid/test/useMachine.test.tsx
index 88a37192f3..9e6ed611b2 100644
--- a/packages/xstate-solid/test/useMachine.test.tsx
+++ b/packages/xstate-solid/test/useMachine.test.tsx
@@ -752,7 +752,7 @@ describe('useMachine hook', () => {
             data-testid="transition-button"
             onclick={() => send({ type: 'TRANSITION' })}
           />
-          <div data-testid="to-json">{toJson().value.toString()}</div>
+          <div data-testid="to-json">{(toJson() as any).value.toString()}</div>
         </div>
       );
     };
diff --git a/packages/xstate-test/src/types.ts b/packages/xstate-test/src/types.ts
index 47cb36a0d4..22876a0d3a 100644
--- a/packages/xstate-test/src/types.ts
+++ b/packages/xstate-test/src/types.ts
@@ -3,7 +3,6 @@ import {
   EventObject,
   MachineConfig,
   MachineTypes,
-  State,
   StateNodeConfig,
   TransitionConfig,
   TypegenConstraint,
@@ -13,7 +12,8 @@ import {
   MachineContext,
   ActorLogic,
   ParameterizedObject,
-  Snapshot
+  Snapshot,
+  MachineSnapshot
 } from 'xstate';
 
 type TODO = any;
@@ -102,11 +102,11 @@ export type TestMachineOptions<
 export interface TestMeta<T, TContext extends MachineContext> {
   test?: (
     testContext: T,
-    state: State<TContext, any, any, any, any>
+    state: MachineSnapshot<TContext, any, any, any, any, any>
   ) => Promise<void> | void;
   description?:
     | string
-    | ((state: State<TContext, any, any, any, any>) => string);
+    | ((state: MachineSnapshot<TContext, any, any, any, any, any>) => string);
   skip?: boolean;
 }
 interface TestStateResult {
@@ -184,7 +184,7 @@ export interface TestTransitionConfig<
   TTestContext
 > extends TransitionConfig<TContext, TEvent, TEvent, TODO, TODO, TODO, string> {
   test?: (
-    state: State<TContext, TEvent, any, any, any>,
+    state: MachineSnapshot<TContext, TEvent, any, any, any, any>,
     testContext: TTestContext
   ) => void;
 }