Repository: excalidraw/excalidraw
File: src/data/restore.ts (TypeScript)

Code before:
  localAppState: Partial<AppState> | null | undefined,
): RestoredAppState => {
  appState = appState || {};

  const defaultAppState = getDefaultAppState();
  const nextAppState = {} as typeof defaultAppState;

  for (const [key, defaultValue] of Object.entries(defaultAppState) as [
    keyof typeof defaultAppState,
    any,
  ][]) {
    const suppliedValue = appState[key];
    const localValue = localAppState ? localAppState[key] : undefined;
    (nextAppState as any)[key] =
      suppliedValue !== undefined
        ? suppliedValue
        : localValue !== undefined
        ? localValue
        : defaultValue;
  }

  return {
    ...nextAppState,
    elementType:
      AllowedExcalidrawElementTypes[nextAppState.elementType] &&
      !isEraserActive(nextAppState)
        ? nextAppState.elementType
        : "selection",
    // Migrates from previous version where appState.zoom was a number
    zoom:
      typeof appState.zoom === "number"
        ? {
            value: appState.zoom as NormalizedZoomValue,
          }
        : appState.zoom || defaultAppState.zoom,
  };
};

export const restore = (
  data: ImportedDataState | null,
  /**
   * Local AppState (`this.state` or initial state from localStorage) so that we
   * don't overwrite local state with default values (when values not
   * explicitly specified).
   * Supply `null` if you can't get access to it.
   */
  localAppState: Partial<AppState> | null | undefined,
  localElements: readonly ExcalidrawElement[] | null | undefined,
): RestoredDataState => {
  return {
    elements: restoreElements(data?.elements, localElements),

Review comment (suggestion):
if we don't want to persist `eraser` tool across sessions, then let's set it as `false` in `AllowedExcalidrawElementTypes` as that's what it's for.

Code after:
  localAppState: Partial<AppState> | null | undefined,
): RestoredAppState => {
  appState = appState || {};

  const defaultAppState = getDefaultAppState();
  const nextAppState = {} as typeof defaultAppState;

  for (const [key, defaultValue] of Object.entries(defaultAppState) as [
    keyof typeof defaultAppState,
    any,
  ][]) {
    const suppliedValue = appState[key];
    const localValue = localAppState ? localAppState[key] : undefined;
    (nextAppState as any)[key] =
      suppliedValue !== undefined
        ? suppliedValue
        : localValue !== undefined
        ? localValue
        : defaultValue;
  }

  return {
    ...nextAppState,
    elementType: AllowedExcalidrawElementTypes[nextAppState.elementType]
      ? nextAppState.elementType
      : "selection",
    // Migrates from previous version where appState.zoom was a number
    zoom:
      typeof appState.zoom === "number"
        ? {
            value: appState.zoom as NormalizedZoomValue,
          }
        : appState.zoom || defaultAppState.zoom,
  };
};

export const restore = (
  data: ImportedDataState | null,
  /**
   * Local AppState (`this.state` or initial state from localStorage) so that we
   * don't overwrite local state with default values (when values not
   * explicitly specified).
   * Supply `null` if you can't get access to it.
   */
  localAppState: Partial<AppState> | null | undefined,
  localElements: readonly ExcalidrawElement[] | null | undefined,
): RestoredDataState => {
  return {
    elements: restoreElements(data?.elements, localElements),
    appState: restoreAppState(data?.appState, localAppState || null),
    files: data?.files || {},