diff --git a/frontend/src/metabase/lib/formatting/nullable.ts b/frontend/src/metabase/lib/formatting/nullable.ts
new file mode 100644
index 0000000000000000000000000000000000000000..efaf102541ff45588c6a0a981a443b93ebcf4023
--- /dev/null
+++ b/frontend/src/metabase/lib/formatting/nullable.ts
@@ -0,0 +1,5 @@
+import { NULL_DISPLAY_VALUE } from "../constants";
+
+export function formatNullable<T>(value: T | null | undefined) {
+  return value ?? NULL_DISPLAY_VALUE;
+}
diff --git a/frontend/src/metabase/static-viz/lib/format.ts b/frontend/src/metabase/static-viz/lib/format.ts
index 944292bb13467a82589e08c8da08a8e380b94831..66d4afeee09eeb064aaddce597c3f19d30dab51d 100644
--- a/frontend/src/metabase/static-viz/lib/format.ts
+++ b/frontend/src/metabase/static-viz/lib/format.ts
@@ -1,5 +1,6 @@
 import moment from "moment";
 import { Moment } from "moment-timezone";
+import { NumberLike, StringLike } from "@visx/scale";
 import {
   DatasetColumn,
   RowValue,
@@ -105,7 +106,7 @@ export const getStaticFormatters = (
   chartColumns: ChartColumns,
   settings: VisualizationSettings,
 ): ChartTicksFormatters => {
-  const yTickFormatter = (value: RowValue) => {
+  const yTickFormatter = (value: StringLike) => {
     const column = chartColumns.dimension.column;
     const columnSettings = settings.column_settings?.[getColumnKey(column)];
 
@@ -120,7 +121,7 @@ export const getStaticFormatters = (
 
   const metricColumn = getLabelsMetricColumn(chartColumns);
 
-  const percentXTicksFormatter = (percent: any) => {
+  const percentXTicksFormatter = (percent: NumberLike) => {
     const column = metricColumn.column;
     const number_separators =
       settings.column_settings?.[getColumnKey(column)]?.number_separators;
@@ -136,7 +137,7 @@ export const getStaticFormatters = (
     );
   };
 
-  const xTickFormatter = (value: any) => {
+  const xTickFormatter = (value: NumberLike) => {
     const column = metricColumn.column;
     const columnSettings = settings.column_settings?.[getColumnKey(column)];
 
@@ -180,6 +181,6 @@ export const getLabelsStaticFormatter = (
 };
 
 export const getColumnValueStaticFormatter = () => {
-  return (value: any, column: DatasetColumn) =>
+  return (value: RowValue, column: DatasetColumn) =>
     String(formatStaticValue(value, { column }));
 };
diff --git a/frontend/src/metabase/visualizations/lib/apply_tooltips.js b/frontend/src/metabase/visualizations/lib/apply_tooltips.js
index 584391ccd9d4ba187fdb1e02440a5f114825b9b3..6956e98c86f4cdffc010b77970a5adba31ecb0f3 100644
--- a/frontend/src/metabase/visualizations/lib/apply_tooltips.js
+++ b/frontend/src/metabase/visualizations/lib/apply_tooltips.js
@@ -5,8 +5,9 @@ import moment from "moment-timezone";
 import { getIn } from "icepick";
 
 import { formatValue } from "metabase/lib/formatting";
+import { formatNullable } from "metabase/lib/formatting/nullable";
 
-import { isNormalized, isStacked, formatNull } from "./renderer_utils";
+import { isNormalized, isStacked } from "./renderer_utils";
 import { determineSeriesIndexFromElement } from "./tooltip";
 import { getFriendlyName } from "./utils";
 
@@ -176,7 +177,7 @@ export function getClickHoverObject(
         }
         return {
           key: getColumnDisplayName(col, colVizSettingsKeys[i]),
-          value: formatNull(aggregatedRow[i]),
+          value: formatNullable(aggregatedRow[i]),
           col: col,
         };
       });
diff --git a/frontend/src/metabase/visualizations/lib/renderer_utils.js b/frontend/src/metabase/visualizations/lib/renderer_utils.js
index e797d0f8baff166baeb59e7bdefda3a4fcd33ea3..a562c862d7458f43aeb9a36162cba9e59a90a0a2 100644
--- a/frontend/src/metabase/visualizations/lib/renderer_utils.js
+++ b/frontend/src/metabase/visualizations/lib/renderer_utils.js
@@ -5,10 +5,10 @@ import { getIn } from "icepick";
 
 import { parseTimestamp } from "metabase/lib/time";
 import {
-  NULL_DISPLAY_VALUE,
   NULL_NUMERIC_VALUE,
   TOTAL_ORDINAL_VALUE,
 } from "metabase/lib/constants";
+import { formatNullable } from "metabase/lib/formatting/nullable";
 import { datasetContainsNoResults } from "metabase-lib/queries/utils/dataset";
 
 import {
@@ -109,7 +109,7 @@ const memoizedParseXValue = _.memoize(
     if (isTimeseries && !isQuantitative) {
       return parseTimestampAndWarn(xValue, unit);
     }
-    const parsedValue = isNumeric ? xValue : String(formatNull(xValue));
+    const parsedValue = isNumeric ? xValue : String(formatNullable(xValue));
     return { parsedValue };
   },
   // create cache key from args
@@ -408,10 +408,6 @@ export const isMultiCardSeries = series =>
   series.length > 1 &&
   getIn(series, [0, "card", "id"]) !== getIn(series, [1, "card", "id"]);
 
-export function formatNull(value) {
-  return value === null ? NULL_DISPLAY_VALUE : value;
-}
-
 // Hack: for numeric dimensions we have to replace null values
 // with anything else since crossfilter groups merge 0 and null
 export function replaceNullValuesForOrdinal(value) {
diff --git a/frontend/src/metabase/visualizations/shared/components/RowChart/types.ts b/frontend/src/metabase/visualizations/shared/components/RowChart/types.ts
index 6b74d2cf946995cf9418d151c5f554aac6c5ed4d..29ea0ce139ca0673be968ee7d36aec38dedd50fb 100644
--- a/frontend/src/metabase/visualizations/shared/components/RowChart/types.ts
+++ b/frontend/src/metabase/visualizations/shared/components/RowChart/types.ts
@@ -1,7 +1,8 @@
+import { StringLike } from "@visx/scale";
 import { AxisStyle, ChartFont, GoalStyle } from "../../types/style";
 
 export type XValue = number | null;
-export type YValue = string | number | boolean;
+export type YValue = string | number | boolean | null;
 
 export type Series<TDatum, TSeriesInfo = unknown> = {
   seriesKey: string;
@@ -14,7 +15,7 @@ export type Series<TDatum, TSeriesInfo = unknown> = {
 export type BarData<TDatum, TSeriesInfo = unknown> = {
   xStartValue: number;
   xEndValue: number;
-  yValue: YValue;
+  yValue: StringLike;
   isNegative: boolean;
   isBorderValue?: boolean;
   datum: TDatum;
diff --git a/frontend/src/metabase/visualizations/shared/components/RowChart/utils/data.ts b/frontend/src/metabase/visualizations/shared/components/RowChart/utils/data.ts
index 3c929efd3952fdb3f6f6999a4c5e688eaaf20a9f..91bfd79053277039f748f7112449225239e0065a 100644
--- a/frontend/src/metabase/visualizations/shared/components/RowChart/utils/data.ts
+++ b/frontend/src/metabase/visualizations/shared/components/RowChart/utils/data.ts
@@ -4,6 +4,7 @@ import type { Series as D3Series } from "d3-shape";
 import d3 from "d3";
 import { ContinuousScaleType } from "metabase/visualizations/shared/types/scale";
 import { isNotNull } from "metabase/core/utils/types";
+import { formatNullable } from "metabase/lib/formatting/nullable";
 import { BarData, Series, SeriesData, StackOffset } from "../types";
 
 export const StackOffsetFn = {
@@ -21,7 +22,7 @@ export const calculateNonStackedBars = <TDatum>(
   return multipleSeries.map((series, seriesIndex) => {
     const bars: BarData<TDatum>[] = data
       .map((datum, datumIndex) => {
-        const yValue = series.yAccessor(datum);
+        const yValue = formatNullable(series.yAccessor(datum));
         const xValue = series.xAccessor(datum);
         const isNegative = xValue != null && xValue < 0;
 
@@ -100,7 +101,7 @@ export const calculateStackedBars = <TDatum>(
 
         const [xStartValue, xEndValue] = stackedDatum;
 
-        const yValue = series.yAccessor(stackedDatum.data);
+        const yValue = formatNullable(series.yAccessor(stackedDatum.data));
         const isNegative = xStartValue < 0;
         const isBorderValue =
           (isNegative && xStartValue === datumMin) ||
diff --git a/frontend/src/metabase/visualizations/shared/components/RowChart/utils/scale.ts b/frontend/src/metabase/visualizations/shared/components/RowChart/utils/scale.ts
index 5c0d3ef0267d62262451514c08b1fb307e25ba6c..3a221109ff9785fb6522454198bc3446c3f7e132 100644
--- a/frontend/src/metabase/visualizations/shared/components/RowChart/utils/scale.ts
+++ b/frontend/src/metabase/visualizations/shared/components/RowChart/utils/scale.ts
@@ -58,7 +58,7 @@ export const getChartScales = <TDatum>(
   rangeOverride?: Range,
 ) => {
   const yDomain = createYDomain(seriesData);
-  const yScale = scaleBand<YValue>({
+  const yScale = scaleBand({
     domain: yDomain,
     range: [0, innerHeight],
     padding: 0.2,
diff --git a/frontend/src/metabase/visualizations/shared/components/RowChartView/RowChartView.tsx b/frontend/src/metabase/visualizations/shared/components/RowChartView/RowChartView.tsx
index 474152237f364bf379107fc81082a819ba25581f..b99d0bbf4cc4649af0c6781fbaa260adc5e89179 100644
--- a/frontend/src/metabase/visualizations/shared/components/RowChartView/RowChartView.tsx
+++ b/frontend/src/metabase/visualizations/shared/components/RowChartView/RowChartView.tsx
@@ -5,7 +5,7 @@ import { Bar } from "@visx/shape";
 import type { NumberValue, ScaleBand, ScaleContinuousNumeric } from "d3-scale";
 import { Text } from "@visx/text";
 import { GridColumns } from "@visx/grid";
-import { scaleBand } from "@visx/scale";
+import { scaleBand, StringLike, NumberLike } from "@visx/scale";
 import { HoveredData } from "metabase/visualizations/shared/types/events";
 import { Margin } from "metabase/visualizations/shared/types/layout";
 import { VerticalGoalLine } from "../VerticalGoalLine/VerticalGoalLine";
@@ -16,12 +16,12 @@ import { getDataLabel } from "./utils/data-labels";
 export interface RowChartViewProps<TDatum> {
   width: number;
   height: number;
-  yScale: ScaleBand<YValue>;
+  yScale: ScaleBand<StringLike>;
   xScale: ScaleContinuousNumeric<number, number, never>;
   seriesData: SeriesData<TDatum>[];
-  labelsFormatter: (value: NumberValue) => string;
-  yTickFormatter: (value: YValue) => string;
-  xTickFormatter: (value: NumberValue) => string;
+  labelsFormatter: (value: NumberLike) => string;
+  yTickFormatter: (value: StringLike) => string;
+  xTickFormatter: (value: NumberLike) => string;
   xTicks: number[];
   goal: {
     label: string;
diff --git a/frontend/src/metabase/visualizations/shared/utils/data.ts b/frontend/src/metabase/visualizations/shared/utils/data.ts
index 064df89b3a2f6b8ca029622a500d11edb015bcfd..c4c42b06759492182f4bb7374c57323331f17148 100644
--- a/frontend/src/metabase/visualizations/shared/utils/data.ts
+++ b/frontend/src/metabase/visualizations/shared/utils/data.ts
@@ -16,7 +16,7 @@ import {
   TwoDimensionalChartData,
 } from "metabase/visualizations/shared/types/data";
 import { Series } from "metabase/visualizations/shared/components/RowChart/types";
-import { NULL_DISPLAY_VALUE } from "metabase/lib/constants";
+import { formatNullable } from "metabase/lib/formatting/nullable";
 import { isMetric } from "metabase-lib/types/utils/isa";
 
 const getMetricValue = (value: RowValue): MetricValue => {
@@ -185,10 +185,7 @@ const getBreakoutSeries = (
     return {
       seriesKey: breakoutName,
       seriesName: breakoutName,
-      yAccessor: (datum: GroupedDatum) =>
-        datum.dimensionValue == null
-          ? NULL_DISPLAY_VALUE
-          : datum.dimensionValue,
+      yAccessor: (datum: GroupedDatum) => formatNullable(datum.dimensionValue),
       xAccessor: (datum: GroupedDatum) =>
         datum.breakout?.[breakoutName]?.[metric.column.name] ?? null,
       seriesInfo: {
@@ -208,8 +205,7 @@ const getMultipleMetricSeries = (
     return {
       seriesKey: metric.column.name,
       seriesName: metric.column.display_name ?? metric.column.name,
-      yAccessor: (datum: GroupedDatum) =>
-        datum.dimensionValue != null ? datum.dimensionValue : "null",
+      yAccessor: (datum: GroupedDatum) => datum.dimensionValue,
       xAccessor: (datum: GroupedDatum) => datum.metrics[metric.column.name],
       seriesInfo: {
         dimensionColumn: dimension.column,
diff --git a/frontend/src/metabase/visualizations/visualizations/RowChart/utils/events.ts b/frontend/src/metabase/visualizations/visualizations/RowChart/utils/events.ts
index 4f2a2fa160d26cf142288405cc6d1b67b18c29e3..b0eae2f1a778c8cc74d08e3b9a570640a6fee57d 100644
--- a/frontend/src/metabase/visualizations/visualizations/RowChart/utils/events.ts
+++ b/frontend/src/metabase/visualizations/visualizations/RowChart/utils/events.ts
@@ -3,7 +3,7 @@ import {
   RowValue,
   VisualizationSettings,
 } from "metabase-types/api";
-import { NULL_DISPLAY_VALUE } from "metabase/lib/constants";
+import { formatNullable } from "metabase/lib/formatting/nullable";
 import { ChartColumns } from "metabase/visualizations/lib/graph/columns";
 import {
   BarData,
@@ -25,7 +25,7 @@ const getMetricColumnData = (
 
     return {
       key: col.display_name,
-      value: value != null ? value : NULL_DISPLAY_VALUE,
+      value: formatNullable(value),
       col,
     };
   });
@@ -40,7 +40,7 @@ const getColumnsData = (
   const data = [
     {
       key: chartColumns.dimension.column.display_name,
-      value: datum.dimensionValue,
+      value: formatNullable(datum.dimensionValue),
       col: chartColumns.dimension.column,
     },
   ];
diff --git a/frontend/src/metabase/visualizations/visualizations/RowChart/utils/format.ts b/frontend/src/metabase/visualizations/visualizations/RowChart/utils/format.ts
index 3bac8f274daa613a4b94aadbdcb0bbe5c8f6b975..2a29dc418aeb6034fac2050920dd7fa38ca5b176 100644
--- a/frontend/src/metabase/visualizations/visualizations/RowChart/utils/format.ts
+++ b/frontend/src/metabase/visualizations/visualizations/RowChart/utils/format.ts
@@ -1,3 +1,4 @@
+import { NumberLike, StringLike } from "@visx/scale";
 import {
   DatasetColumn,
   RowValue,
@@ -16,7 +17,7 @@ export const getFormatters = (
   chartColumns: ChartColumns,
   settings: VisualizationSettings,
 ): ChartTicksFormatters => {
-  const yTickFormatter = (value: RowValue) => {
+  const yTickFormatter = (value: StringLike) => {
     return String(
       formatValue(value, {
         ...settings.column(chartColumns.dimension.column),
@@ -27,7 +28,7 @@ export const getFormatters = (
 
   const metricColumn = getLabelsMetricColumn(chartColumns);
 
-  const percentXTicksFormatter = (percent: any) => {
+  const percentXTicksFormatter = (percent: NumberLike) => {
     const column = metricColumn.column;
     const number_separators = settings.column(column)?.number_separators;
 
@@ -42,7 +43,7 @@ export const getFormatters = (
     );
   };
 
-  const xTickFormatter = (value: any) => {
+  const xTickFormatter = (value: NumberLike) => {
     return String(
       formatValue(value, {
         ...settings.column(metricColumn.column),
@@ -80,6 +81,6 @@ export const getLabelsFormatter = (
 };
 
 export const getColumnValueFormatter = () => {
-  return (value: any, column: DatasetColumn) =>
+  return (value: RowValue, column: DatasetColumn) =>
     String(formatValue(value, { column }));
 };