diff --git a/frontend/src/metabase/dashboard/components/DashCard/DashCard.tsx b/frontend/src/metabase/dashboard/components/DashCard/DashCard.tsx
index 6b46192871f327bf8bf46085a6c191be947176be..1489c309850b4b103f4f86e5db19ae54ed0285d4 100644
--- a/frontend/src/metabase/dashboard/components/DashCard/DashCard.tsx
+++ b/frontend/src/metabase/dashboard/components/DashCard/DashCard.tsx
@@ -76,7 +76,7 @@ export interface DashCardProps {
   navigateToNewCardFromDashboard?: (
     opts: NavigateToNewCardFromDashboardOpts,
   ) => void;
-  onReplaceAllVisualizationSettings: (
+  onReplaceAllDashCardVisualizationSettings: (
     dashcardId: DashCardId,
     settings: VisualizationSettings,
   ) => void;
@@ -114,7 +114,7 @@ function DashCardInner({
   showClickBehaviorSidebar,
   onChangeLocation,
   onUpdateVisualizationSettings,
-  onReplaceAllVisualizationSettings,
+  onReplaceAllDashCardVisualizationSettings,
   downloadsEnabled,
 }: DashCardProps) {
   const dashcardData = useSelector(state =>
@@ -326,8 +326,8 @@ function DashCardInner({
             onRemove={onRemove}
             onReplaceCard={onReplaceCard}
             onUpdateVisualizationSettings={onUpdateVisualizationSettings}
-            onReplaceAllVisualizationSettings={
-              onReplaceAllVisualizationSettings
+            onReplaceAllDashCardVisualizationSettings={
+              onReplaceAllDashCardVisualizationSettings
             }
             showClickBehaviorSidebar={handleShowClickBehaviorSidebar}
             onPreviewToggle={handlePreviewToggle}
diff --git a/frontend/src/metabase/dashboard/components/DashCard/DashCardActionsPanel/DashCardActionsPanel.tsx b/frontend/src/metabase/dashboard/components/DashCard/DashCardActionsPanel/DashCardActionsPanel.tsx
index 85a096fbc32ed8f84b41c4deeae65f781d54243d..6fb103819945fc3428c965b6157003aef29c5367 100644
--- a/frontend/src/metabase/dashboard/components/DashCard/DashCardActionsPanel/DashCardActionsPanel.tsx
+++ b/frontend/src/metabase/dashboard/components/DashCard/DashCardActionsPanel/DashCardActionsPanel.tsx
@@ -36,7 +36,7 @@ interface Props {
   onRemove: (dashcard: DashboardCard) => void;
   onAddSeries: (dashcard: DashboardCard) => void;
   onReplaceCard: (dashcard: DashboardCard) => void;
-  onReplaceAllVisualizationSettings: (
+  onReplaceAllDashCardVisualizationSettings: (
     dashcardId: DashCardId,
     settings: VisualizationSettings,
   ) => void;
@@ -60,7 +60,7 @@ function DashCardActionsPanelInner({
   onRemove,
   onAddSeries,
   onReplaceCard,
-  onReplaceAllVisualizationSettings,
+  onReplaceAllDashCardVisualizationSettings,
   onUpdateVisualizationSettings,
   showClickBehaviorSidebar,
   onPreviewToggle,
@@ -95,9 +95,9 @@ function DashCardActionsPanelInner({
         return;
       }
 
-      onReplaceAllVisualizationSettings(dashcard.id, settings);
+      onReplaceAllDashCardVisualizationSettings(dashcard.id, settings);
     },
-    [dashcard, onReplaceAllVisualizationSettings],
+    [dashcard, onReplaceAllDashCardVisualizationSettings],
   );
 
   const handleReplaceCard = useCallback(() => {
diff --git a/frontend/src/metabase/dashboard/components/DashCard/Dashcard.unit.spec.tsx b/frontend/src/metabase/dashboard/components/DashCard/Dashcard.unit.spec.tsx
index 078e751f440d2576e7d646b216574a86d91cbf14..e3f29c576391b73166edc5f4b3397b267bcf69c2 100644
--- a/frontend/src/metabase/dashboard/components/DashCard/Dashcard.unit.spec.tsx
+++ b/frontend/src/metabase/dashboard/components/DashCard/Dashcard.unit.spec.tsx
@@ -84,7 +84,7 @@ function setup({
       onRemove={jest.fn()}
       markNewCardSeen={jest.fn()}
       navigateToNewCardFromDashboard={jest.fn()}
-      onReplaceAllVisualizationSettings={jest.fn()}
+      onReplaceAllDashCardVisualizationSettings={jest.fn()}
       onUpdateVisualizationSettings={jest.fn()}
       showClickBehaviorSidebar={jest.fn()}
       onChangeLocation={jest.fn()}
diff --git a/frontend/src/metabase/dashboard/components/DashboardGrid.tsx b/frontend/src/metabase/dashboard/components/DashboardGrid.tsx
index 8bbc98b9fa2dd6015cd5fc93a0cbbec4e6fd26e4..5f65b0d112c5ebe3cda3625bf4436f42f7f7bb3e 100644
--- a/frontend/src/metabase/dashboard/components/DashboardGrid.tsx
+++ b/frontend/src/metabase/dashboard/components/DashboardGrid.tsx
@@ -523,7 +523,7 @@ class DashboardGrid extends Component<DashboardGridProps, DashboardGridState> {
         onUpdateVisualizationSettings={
           this.props.onUpdateDashCardVisualizationSettings
         }
-        onReplaceAllVisualizationSettings={
+        onReplaceAllDashCardVisualizationSettings={
           this.props.onReplaceAllDashCardVisualizationSettings
         }
         mode={this.props.mode}
diff --git a/frontend/src/metabase/query_builder/actions/visualization-settings.js b/frontend/src/metabase/query_builder/actions/visualization-settings.ts
similarity index 74%
rename from frontend/src/metabase/query_builder/actions/visualization-settings.js
rename to frontend/src/metabase/query_builder/actions/visualization-settings.ts
index 9c3c4d9c691821a5e45aede5c05a76d5d7639f19..af5723003de859d19631a0c62708618567898898 100644
--- a/frontend/src/metabase/query_builder/actions/visualization-settings.js
+++ b/frontend/src/metabase/query_builder/actions/visualization-settings.ts
@@ -1,4 +1,7 @@
 import * as Lib from "metabase-lib";
+import type Question from "metabase-lib/v1/Question";
+import type { VisualizationSettings } from "metabase-types/api";
+import type { Dispatch, GetState } from "metabase-types/store";
 
 import {
   getDatasetEditorTab,
@@ -9,9 +12,11 @@ import {
 
 import { updateQuestion } from "./core";
 
-export const updateCardVisualizationSettings =
-  settings => async (dispatch, getState) => {
+export const onUpdateVisualizationSettings =
+  (settings: VisualizationSettings) =>
+  async (dispatch: Dispatch, getState: GetState) => {
     const question = getQuestion(getState());
+
     const previousQueryBuilderMode = getPreviousQueryBuilderMode(getState());
     const queryBuilderMode = getQueryBuilderMode(getState());
     const datasetEditorTab = getDatasetEditorTab(getState());
@@ -26,24 +31,25 @@ export const updateCardVisualizationSettings =
       settings["table.column_widths"] === undefined;
 
     if (
-      (isEditingDatasetMetadata || wasJustEditingModel) &&
-      isColumnWidthResetEvent
+      !question ||
+      ((isEditingDatasetMetadata || wasJustEditingModel) &&
+        isColumnWidthResetEvent)
     ) {
       return;
     }
 
     // The check allows users without data permission to resize/rearrange columns
     const { isEditable } = Lib.queryDisplayInfo(question.query());
-    const hasWritePermissions = isEditable;
     await dispatch(
       updateQuestion(question.updateSettings(settings), {
-        shouldUpdateUrl: hasWritePermissions,
+        shouldUpdateUrl: isEditable,
       }),
     );
   };
 
-export const replaceAllCardVisualizationSettings =
-  (settings, newQuestion) => async (dispatch, getState) => {
+export const onReplaceAllVisualizationSettings =
+  (settings: VisualizationSettings, newQuestion: Question) =>
+  async (dispatch: Dispatch, getState: GetState) => {
     const oldQuestion = getQuestion(getState());
     const updatedQuestion = (newQuestion ?? oldQuestion).setSettings(settings);
     const { isEditable } = Lib.queryDisplayInfo(updatedQuestion.query());
@@ -57,8 +63,3 @@ export const replaceAllCardVisualizationSettings =
       }),
     );
   };
-
-// these are just temporary mappings to appease the existing QB code and it's naming prefs
-export const onUpdateVisualizationSettings = updateCardVisualizationSettings;
-export const onReplaceAllVisualizationSettings =
-  replaceAllCardVisualizationSettings;