diff --git a/frontend/src/metabase-lib/lib/Mode.ts b/frontend/src/metabase-lib/lib/Mode/Mode.ts
similarity index 78%
rename from frontend/src/metabase-lib/lib/Mode.ts
rename to frontend/src/metabase-lib/lib/Mode/Mode.ts
index 0bae53dff72724c7fff82ee4328db5ab262b2799..f92ade62aa60661369e73eb199fa78f49caedc39 100644
--- a/frontend/src/metabase-lib/lib/Mode.ts
+++ b/frontend/src/metabase-lib/lib/Mode/Mode.ts
@@ -1,5 +1,3 @@
-// eslint-disable-next-line @typescript-eslint/ban-ts-comment
-// @ts-nocheck
 import Question from "metabase-lib/lib/Question";
 import { getMode } from "metabase/modes/lib/modes";
 import {
@@ -7,6 +5,7 @@ import {
   ClickObject,
   QueryMode,
 } from "metabase-types/types/Visualization";
+
 export default class Mode {
   _question: Question;
   _queryMode: QueryMode;
@@ -16,15 +15,14 @@ export default class Mode {
     this._queryMode = queryMode;
   }
 
-  static forQuestion(question: Question): Mode | null | undefined {
+  static forQuestion(question: Question): Mode | null {
     // TODO Atte Keinänen 6/22/17: Move getMode here and refactor it after writing tests
     const queryMode = getMode(question);
-
     if (queryMode) {
       return new Mode(question, queryMode);
-    } else {
-      return null;
     }
+
+    return null;
   }
 
   queryMode() {
@@ -36,9 +34,9 @@ export default class Mode {
   }
 
   actionsForClick(
-    clicked: ClickObject | null | undefined,
-    settings,
-    extraData,
+    clicked: ClickObject | undefined,
+    settings: Record<string, any>,
+    extraData: Record<string, any>,
   ): ClickAction[] {
     return this._queryMode.drills().flatMap(actionCreator =>
       actionCreator({
diff --git a/frontend/src/metabase-lib/lib/Mode/constants.ts b/frontend/src/metabase-lib/lib/Mode/constants.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7f853f7377e56185969fe31090a599754f632e8a
--- /dev/null
+++ b/frontend/src/metabase-lib/lib/Mode/constants.ts
@@ -0,0 +1,17 @@
+export const MODE_TYPE_DEFAULT = "default";
+export const MODE_TYPE_NATIVE = "native";
+export const MODE_TYPE_SEGMENT = "segment";
+export const MODE_TYPE_METRIC = "metric";
+export const MODE_TYPE_TIMESERIES = "timeseries";
+export const MODE_TYPE_GEO = "geo";
+export const MODE_TYPE_PIVOT = "pivot";
+
+export const MODES_TYPES = [
+  MODE_TYPE_NATIVE,
+  MODE_TYPE_SEGMENT,
+  MODE_TYPE_METRIC,
+  MODE_TYPE_TIMESERIES,
+  MODE_TYPE_GEO,
+  MODE_TYPE_PIVOT,
+  MODE_TYPE_DEFAULT,
+] as const;
diff --git a/frontend/src/metabase-lib/lib/Mode/index.ts b/frontend/src/metabase-lib/lib/Mode/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e42afab4d3da45a9432e8595cfbdbb5e4004495c
--- /dev/null
+++ b/frontend/src/metabase-lib/lib/Mode/index.ts
@@ -0,0 +1,2 @@
+export { default } from "./Mode";
+export { getMode } from "./utils";
diff --git a/frontend/src/metabase-lib/lib/Mode/types.ts b/frontend/src/metabase-lib/lib/Mode/types.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6dff0cb96bb0873dbe6878f3a92b4672eea1473b
--- /dev/null
+++ b/frontend/src/metabase-lib/lib/Mode/types.ts
@@ -0,0 +1,3 @@
+import { MODES_TYPES } from "./constants";
+
+export type ModeType = typeof MODES_TYPES[number];
diff --git a/frontend/src/metabase/modes/lib/modes.js b/frontend/src/metabase-lib/lib/Mode/utils.ts
similarity index 65%
rename from frontend/src/metabase/modes/lib/modes.js
rename to frontend/src/metabase-lib/lib/Mode/utils.ts
index 73cb7f321cbc8e1e91d7536397890372fdd3d78c..5722f0cf98333e18a2fff88a69fa28ae14d58308 100644
--- a/frontend/src/metabase/modes/lib/modes.js
+++ b/frontend/src/metabase-lib/lib/Mode/utils.ts
@@ -1,15 +1,18 @@
-import SegmentMode from "../components/modes/SegmentMode";
-import MetricMode from "../components/modes/MetricMode";
-import TimeseriesMode from "../components/modes/TimeseriesMode";
-import GeoMode from "../components/modes/GeoMode";
-import PivotMode from "../components/modes/PivotMode";
-import NativeMode from "../components/modes/NativeMode";
-import DefaultMode from "../components/modes/DefaultMode";
-
+import Question from "metabase-lib/lib/Question";
 import StructuredQuery from "metabase-lib/lib/queries/StructuredQuery";
 import NativeQuery from "metabase-lib/lib/queries/NativeQuery";
+import { ModeType } from "./types";
+import {
+  MODE_TYPE_NATIVE,
+  MODE_TYPE_SEGMENT,
+  MODE_TYPE_METRIC,
+  MODE_TYPE_TIMESERIES,
+  MODE_TYPE_GEO,
+  MODE_TYPE_PIVOT,
+  MODE_TYPE_DEFAULT,
+} from "metabase-lib/lib/Mode/constants";
 
-export function getMode(question) {
+export function getMode(question: Question): ModeType | null {
   if (!question) {
     return null;
   }
@@ -17,7 +20,7 @@ export function getMode(question) {
   const query = question.query();
 
   if (query instanceof NativeQuery) {
-    return NativeMode;
+    return MODE_TYPE_NATIVE;
   }
 
   if (query instanceof StructuredQuery) {
@@ -25,11 +28,13 @@ export function getMode(question) {
     const breakouts = query.breakouts();
 
     if (aggregations.length === 0 && breakouts.length === 0) {
-      return SegmentMode;
+      return MODE_TYPE_SEGMENT;
     }
+
     if (aggregations.length > 0 && breakouts.length === 0) {
-      return MetricMode;
+      return MODE_TYPE_METRIC;
     }
+
     if (aggregations.length > 0 && breakouts.length > 0) {
       const breakoutFields = breakouts.map(b => b.field());
       if (
@@ -38,21 +43,23 @@ export function getMode(question) {
           breakoutFields[0].isDate() &&
           breakoutFields[1].isCategory())
       ) {
-        return TimeseriesMode;
+        return MODE_TYPE_TIMESERIES;
       }
+
       if (breakoutFields.length === 1 && breakoutFields[0].isAddress()) {
-        return GeoMode;
+        return MODE_TYPE_GEO;
       }
+
       if (
         (breakoutFields.length === 1 && breakoutFields[0].isCategory()) ||
         (breakoutFields.length === 2 &&
           breakoutFields[0].isCategory() &&
           breakoutFields[1].isCategory())
       ) {
-        return PivotMode;
+        return MODE_TYPE_PIVOT;
       }
     }
   }
 
-  return DefaultMode;
+  return MODE_TYPE_DEFAULT;
 }
diff --git a/frontend/src/metabase-types/types/Database.ts b/frontend/src/metabase-types/types/Database.ts
index 60cda7f51b20955f683ab21ef3b7e6b6d04e447a..3ddd49f3aedb864fbd3a30da42e7bdfbc2f5a867 100644
--- a/frontend/src/metabase-types/types/Database.ts
+++ b/frontend/src/metabase-types/types/Database.ts
@@ -16,9 +16,7 @@ export type DatabaseFeature =
   | "case-sensitivity-string-filter-options"
   | "binning";
 
-export type DatabaseDetails = {
-  [key: string]: any;
-};
+export type DatabaseDetails = Record<string, any>;
 
 export type DatabaseEngine = string;
 
diff --git a/frontend/src/metabase-types/types/Visualization.ts b/frontend/src/metabase-types/types/Visualization.ts
index de62082172af382b4820eff93facce14bb8320a3..257190104b5d7af99ca6aac30243f75dc1bc2ac3 100644
--- a/frontend/src/metabase-types/types/Visualization.ts
+++ b/frontend/src/metabase-types/types/Visualization.ts
@@ -35,12 +35,12 @@ export type ClickObject = {
   event?: MouseEvent;
   element?: HTMLElement;
   seriesIndex?: number;
-  settings?: { [key: string]: any };
+  settings?: Record<string, any>;
   origin?: {
     row: Row;
     cols: Column[];
   };
-  extraData?: { [key: string]: any };
+  extraData?: Record<string, any>;
 };
 
 export type ClickAction = {
@@ -59,6 +59,8 @@ export type ClickAction = {
 export type ClickActionProps = {
   question: Question;
   clicked?: ClickObject;
+  settings?: VisualizationSettings;
+  extraData?: Record<string, any>;
 };
 
 export type OnChangeCardAndRun = ({
diff --git a/frontend/src/metabase-types/types/index.ts b/frontend/src/metabase-types/types/index.ts
index c7e847db72027d94a3c9c47e6b548f8ede44cde2..0978d8bba209e1d609f183fc0b4583bfd55fbaef 100644
--- a/frontend/src/metabase-types/types/index.ts
+++ b/frontend/src/metabase-types/types/index.ts
@@ -15,13 +15,11 @@ export type LocationDescriptor = {
   hash: string;
   pathname: string;
   search?: string;
-  query?: { [key: string]: string };
+  query?: Record<string, any>;
 };
 
 /* Map of query string names to string values */
-export type QueryParams = {
-  [key: string]: string;
-};
+export type QueryParams = Record<string, any>;
 
 /* Metabase API error object returned by the backend */
 export type ApiError = {
diff --git a/frontend/src/metabase/modes/lib/modes.ts b/frontend/src/metabase/modes/lib/modes.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1bc3bf784dc4ed0b17d8450acfa01413fb1837f9
--- /dev/null
+++ b/frontend/src/metabase/modes/lib/modes.ts
@@ -0,0 +1,49 @@
+import SegmentMode from "../components/modes/SegmentMode";
+import MetricMode from "../components/modes/MetricMode";
+import TimeseriesMode from "../components/modes/TimeseriesMode";
+import GeoMode from "../components/modes/GeoMode";
+import PivotMode from "../components/modes/PivotMode";
+import NativeMode from "../components/modes/NativeMode";
+import DefaultMode from "../components/modes/DefaultMode";
+import { QueryMode } from "metabase-types/types/Visualization";
+
+import Question from "metabase-lib/lib/Question";
+import { getMode as getModeFromLib } from "metabase-lib/lib/Mode";
+import {
+  MODE_TYPE_NATIVE,
+  MODE_TYPE_SEGMENT,
+  MODE_TYPE_METRIC,
+  MODE_TYPE_TIMESERIES,
+  MODE_TYPE_GEO,
+  MODE_TYPE_PIVOT,
+} from "metabase-lib/lib/Mode/constants";
+
+export function getMode(question: Question): QueryMode | any | null {
+  const mode = getModeFromLib(question);
+  if (!mode) {
+    return null;
+  }
+
+  switch (mode) {
+    case MODE_TYPE_NATIVE:
+      return NativeMode;
+
+    case MODE_TYPE_SEGMENT:
+      return SegmentMode;
+
+    case MODE_TYPE_METRIC:
+      return MetricMode;
+
+    case MODE_TYPE_TIMESERIES:
+      return TimeseriesMode;
+
+    case MODE_TYPE_GEO:
+      return GeoMode;
+
+    case MODE_TYPE_PIVOT:
+      return PivotMode;
+
+    default:
+      return DefaultMode;
+  }
+}
diff --git a/frontend/src/metabase/static-viz/lib/dates.ts b/frontend/src/metabase/static-viz/lib/dates.ts
index 9f3bc2a55d9466c4f2cddc981e4ca47ad58e1c5c..451ad2e965a2421ad40d74f1963121d33eb9b022 100644
--- a/frontend/src/metabase/static-viz/lib/dates.ts
+++ b/frontend/src/metabase/static-viz/lib/dates.ts
@@ -14,7 +14,7 @@ const DEFAULT_OPTIONS = {
   time_enabled: false,
 };
 
-const DATE_FORMATS: { [key: string]: Intl.DateTimeFormat } = {
+const DATE_FORMATS: Record<string, Intl.DateTimeFormat> = {
   YY: new Intl.DateTimeFormat("en", { year: "2-digit" }),
   YYYY: new Intl.DateTimeFormat("en", { year: "numeric" }),
   M: new Intl.DateTimeFormat("en", { month: "numeric" }),
diff --git a/frontend/src/metabase/visualizations/components/ObjectDetail/ObjectDetail.tsx b/frontend/src/metabase/visualizations/components/ObjectDetail/ObjectDetail.tsx
index 285664a9b01107ab5ab433656d3f58f03aa44590..a5a1f182a5801bf2a2e2c54a388ce268b783da57 100644
--- a/frontend/src/metabase/visualizations/components/ObjectDetail/ObjectDetail.tsx
+++ b/frontend/src/metabase/visualizations/components/ObjectDetail/ObjectDetail.tsx
@@ -203,7 +203,7 @@ export function ObjectDetailFn({
   );
 
   const onKeyDown = (event: KeyboardEvent) => {
-    const capturedKeys: { [key: string]: () => void } = {
+    const capturedKeys: Record<string, () => void> = {
       ArrowUp: viewPreviousObjectDetail,
       ArrowDown: viewNextObjectDetail,
       Escape: closeObjectDetail,