diff --git a/frontend/src/metabase-lib/lib/Dimension.ts b/frontend/src/metabase-lib/lib/Dimension.ts
index bbd20921652f1a1a443bc2811cef1c5d45e0071f..b5a179f068344ffec5251767868db703c3938dcb 100644
--- a/frontend/src/metabase-lib/lib/Dimension.ts
+++ b/frontend/src/metabase-lib/lib/Dimension.ts
@@ -13,11 +13,10 @@ import {
 } from "metabase-types/types/Query";
 import { VariableTarget } from "metabase-types/types/Parameter";
 import { IconName } from "metabase-types/types";
-import { getFieldValues, getRemappings } from "metabase/lib/query/field";
 import { DATETIME_UNITS, formatBucketing } from "metabase/lib/query_time";
 import { infer, MONOTYPE } from "metabase/lib/expressions/typeinferencer";
 import { isa } from "cljs/metabase.types";
-import { TemplateTagVariable } from "metabase-lib/lib/Variable";
+import TemplateTagVariable from "metabase-lib/lib/variables/TemplateTagVariable";
 import Field from "metabase-lib/lib/metadata/Field";
 import {
   AggregationOperator,
diff --git a/frontend/src/metabase-lib/lib/Variable.ts b/frontend/src/metabase-lib/lib/Variable.ts
deleted file mode 100644
index e8871d8b89aeff21de82823526f559df54f19a96..0000000000000000000000000000000000000000
--- a/frontend/src/metabase-lib/lib/Variable.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-// eslint-disable-next-line @typescript-eslint/ban-ts-comment
-// @ts-nocheck
-import { TemplateTag } from "metabase-types/types/Query";
-import Metadata from "metabase-lib/lib/metadata/Metadata";
-import Query from "metabase-lib/lib/queries/Query";
-import NativeQuery from "metabase-lib/lib/queries/NativeQuery";
-export default class Variable {
-  _args: any;
-  _metadata: Metadata | null | undefined;
-  _query: Query | null | undefined;
-
-  constructor(args: any[], metadata?: Metadata, query?: Query) {
-    this._args = args;
-    this._metadata = metadata || (query && query.metadata());
-    this._query = query;
-  }
-}
-const VARIABLE_ICONS = {
-  text: "string",
-  number: "int",
-  date: "calendar",
-  dimension: null,
-};
-export class TemplateTagVariable extends Variable {
-  tag(): TemplateTag | null | undefined {
-    if (this._query instanceof NativeQuery) {
-      return this._query.templateTagsMap()[this._args[0]];
-    }
-  }
-
-  displayName() {
-    const tag = this.tag();
-    return tag && (tag["display-name"] || tag.name);
-  }
-
-  icon() {
-    const tag = this.tag();
-    return tag && VARIABLE_ICONS[tag.type];
-  }
-
-  mbql() {
-    return ["template-tag", this._args[0]];
-  }
-}
diff --git a/frontend/src/metabase-lib/lib/queries/NativeQuery.ts b/frontend/src/metabase-lib/lib/queries/NativeQuery.ts
index 8fc668b8b8011a795763849a4c7085910e5eb514..5a12bba3f456ba538b051f0bacfe102ccc079dbb 100644
--- a/frontend/src/metabase-lib/lib/queries/NativeQuery.ts
+++ b/frontend/src/metabase-lib/lib/queries/NativeQuery.ts
@@ -23,11 +23,12 @@ import Question from "metabase-lib/lib/Question";
 import Table from "metabase-lib/lib/metadata/Table";
 import Database from "metabase-lib/lib/metadata/Database";
 import AtomicQuery from "metabase-lib/lib/queries/AtomicQuery";
+import Variable from "metabase-lib/lib/variables/Variable";
+import TemplateTagVariable from "metabase-lib/lib/variables/TemplateTagVariable";
 import { createTemplateTag } from "metabase-lib/lib/queries/TemplateTag";
 import ValidationError from "metabase-lib/lib/ValidationError";
-import DimensionOptions from "../DimensionOptions";
-import Variable, { TemplateTagVariable } from "../Variable";
 import Dimension, { TemplateTagDimension, FieldDimension } from "../Dimension";
+import DimensionOptions from "../DimensionOptions";
 
 import { getNativeQueryTable } from "./utils/native-query-table";
 
diff --git a/frontend/src/metabase-lib/lib/queries/Query.ts b/frontend/src/metabase-lib/lib/queries/Query.ts
index 960867ec5b8da91aaea75a747f507a1db35f04e1..43f6cdec7ecee9f92135800c047c33629e48afef 100644
--- a/frontend/src/metabase-lib/lib/queries/Query.ts
+++ b/frontend/src/metabase-lib/lib/queries/Query.ts
@@ -5,7 +5,7 @@ import { DependentMetadataItem } from "metabase-types/types/Query";
 import Metadata from "metabase-lib/lib/metadata/Metadata";
 import Question from "metabase-lib/lib/Question";
 import Dimension from "metabase-lib/lib/Dimension";
-import Variable from "metabase-lib/lib/Variable";
+import Variable from "metabase-lib/lib/variables/Variable";
 import { memoizeClass } from "metabase-lib/lib/utils";
 import DimensionOptions from "metabase-lib/lib/DimensionOptions";
 
@@ -14,7 +14,7 @@ type QueryUpdateFn = (datasetQuery: DatasetQuery) => void;
  * An abstract class for all query types (StructuredQuery & NativeQuery)
  */
 
-class Query {
+class QueryInner {
   _metadata: Metadata;
 
   /**
@@ -66,7 +66,7 @@ class Query {
     return this._datasetQuery;
   }
 
-  setDatasetQuery(datasetQuery: DatasetQuery): Query {
+  setDatasetQuery(datasetQuery: DatasetQuery): QueryInner {
     return this;
   }
 
@@ -116,7 +116,7 @@ class Query {
     return [];
   }
 
-  setDefaultQuery(): Query {
+  setDefaultQuery(): QueryInner {
     return this;
   }
 
@@ -132,4 +132,6 @@ class Query {
   }
 }
 
-export default memoizeClass<Query>("question")(Query);
+export default class Query extends memoizeClass<QueryInner>("question")(
+  QueryInner,
+) {}
diff --git a/frontend/src/metabase-lib/lib/variables/TemplateTagVariable/TemplateTagVariable.ts b/frontend/src/metabase-lib/lib/variables/TemplateTagVariable/TemplateTagVariable.ts
new file mode 100644
index 0000000000000000000000000000000000000000..260fba1cb154902ba0855a541887fc5dd46c94e1
--- /dev/null
+++ b/frontend/src/metabase-lib/lib/variables/TemplateTagVariable/TemplateTagVariable.ts
@@ -0,0 +1,26 @@
+import { TemplateTag } from "metabase-types/types/Query";
+import Variable from "metabase-lib/lib/variables/Variable";
+import NativeQuery from "metabase-lib/lib/queries/NativeQuery";
+import { VARIABLE_ICONS } from "./constants";
+
+export default class TemplateTagVariable extends Variable {
+  tag(): TemplateTag | null | undefined {
+    if (this._query instanceof NativeQuery) {
+      return this._query.templateTagsMap()[this._args[0]];
+    }
+  }
+
+  displayName(): string | null | undefined {
+    const tag = this.tag();
+    return tag && (tag["display-name"] || tag.name);
+  }
+
+  icon(): string | null | undefined {
+    const tag = this.tag();
+    return tag && VARIABLE_ICONS[tag.type];
+  }
+
+  mbql() {
+    return ["template-tag", this._args[0]];
+  }
+}
diff --git a/frontend/src/metabase-lib/lib/variables/TemplateTagVariable/constants.ts b/frontend/src/metabase-lib/lib/variables/TemplateTagVariable/constants.ts
new file mode 100644
index 0000000000000000000000000000000000000000..88c18ee07cae32703aaa99e9f100c9da548da23f
--- /dev/null
+++ b/frontend/src/metabase-lib/lib/variables/TemplateTagVariable/constants.ts
@@ -0,0 +1,10 @@
+import { TemplateTagType } from "metabase-types/types/Query";
+
+export const VARIABLE_ICONS: Record<TemplateTagType, string | null> = {
+  text: "string",
+  number: "int",
+  date: "calendar",
+  dimension: null,
+  card: null,
+  snippet: null,
+};
diff --git a/frontend/src/metabase-lib/lib/variables/TemplateTagVariable/index.ts b/frontend/src/metabase-lib/lib/variables/TemplateTagVariable/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fb06f4d9a0861d86fc81df8f909fadff257f54aa
--- /dev/null
+++ b/frontend/src/metabase-lib/lib/variables/TemplateTagVariable/index.ts
@@ -0,0 +1 @@
+export { default } from "./TemplateTagVariable";
diff --git a/frontend/src/metabase-lib/lib/variables/Variable/Variable.ts b/frontend/src/metabase-lib/lib/variables/Variable/Variable.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c8293dc76306950242a115294a3979f45650a4d7
--- /dev/null
+++ b/frontend/src/metabase-lib/lib/variables/Variable/Variable.ts
@@ -0,0 +1,14 @@
+import Query from "metabase-lib/lib/queries/Query";
+import Metadata from "metabase-lib/lib/metadata/Metadata";
+
+export default class Variable {
+  _args: any[];
+  _metadata: Metadata | null | undefined;
+  _query: Query | null | undefined;
+
+  constructor(args: any[], metadata?: Metadata, query?: Query) {
+    this._args = args;
+    this._metadata = metadata || (query && query.metadata());
+    this._query = query;
+  }
+}
diff --git a/frontend/src/metabase-lib/lib/variables/Variable/index.ts b/frontend/src/metabase-lib/lib/variables/Variable/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b86535cf2da2a3348e07006e8cb01ef4591a8a52
--- /dev/null
+++ b/frontend/src/metabase-lib/lib/variables/Variable/index.ts
@@ -0,0 +1 @@
+export { default } from "./Variable";
diff --git a/frontend/src/metabase-lib/mocks.ts b/frontend/src/metabase-lib/mocks.ts
index 1723f854458de67045d19851fc0484101fd4c51b..34bed80725e3a857196283e80f7267a301feae6d 100644
--- a/frontend/src/metabase-lib/mocks.ts
+++ b/frontend/src/metabase-lib/mocks.ts
@@ -15,6 +15,7 @@ import {
 import Question from "./lib/Question";
 import NativeQuery from "./lib/queries/NativeQuery";
 import StructuredQuery from "./lib/queries/StructuredQuery";
+import Query from "./lib/queries/Query";
 
 type NativeSavedCard = SavedCard<NativeDatasetQuery>;
 type NativeUnsavedCard = UnsavedCard<NativeDatasetQuery>;
@@ -74,7 +75,7 @@ export function getCleanStructuredQuestion(
 ) {
   let question = getAdHocQuestion(card);
   if (question.query() instanceof StructuredQuery) {
-    question = question.setQuery({});
+    question = question.setQuery(new Query());
   }
   return question;
 }
diff --git a/frontend/src/metabase/lib/click-behavior.js b/frontend/src/metabase/lib/click-behavior.js
index f0da54baf8523986dc9f88eda076ad685c2d12a3..47cabea0208865f0b1f347da2cd8332b93795a0d 100644
--- a/frontend/src/metabase/lib/click-behavior.js
+++ b/frontend/src/metabase/lib/click-behavior.js
@@ -4,15 +4,15 @@ import { t, ngettext, msgid } from "ttag";
 
 import { isDate } from "metabase/lib/schema_metadata";
 import { parseTimestamp } from "metabase/lib/time";
-import { formatDateTimeForParameter } from "metabase/lib/formatting/date";
 import { isa, TYPE } from "metabase/lib/types";
+import { formatDateTimeForParameter } from "metabase/lib/formatting/date";
 import {
   dimensionFilterForParameter,
   variableFilterForParameter,
 } from "metabase/parameters/utils/filters";
 import { isValidImplicitActionClickBehavior } from "metabase/writeback/utils";
 import Question from "metabase-lib/lib/Question";
-import { TemplateTagVariable } from "metabase-lib/lib/Variable";
+import TemplateTagVariable from "metabase-lib/lib/variables/TemplateTagVariable";
 import { TemplateTagDimension } from "metabase-lib/lib/Dimension";
 
 export function getDataFromClicked({
diff --git a/frontend/src/metabase/parameters/utils/filters.js b/frontend/src/metabase/parameters/utils/filters.js
index 5bead4697ad0e6024586e3819938793d34641091..f4fdd8577488ce92034adee726c062cbe76b2439 100644
--- a/frontend/src/metabase/parameters/utils/filters.js
+++ b/frontend/src/metabase/parameters/utils/filters.js
@@ -1,4 +1,4 @@
-import { TemplateTagVariable } from "metabase-lib/lib/Variable";
+import TemplateTagVariable from "metabase-lib/lib/variables/TemplateTagVariable";
 import { getParameterType, getParameterSubType } from "./parameter-type";
 import { getParameterOperatorName } from "./operators";
 
diff --git a/frontend/src/metabase/parameters/utils/mapping-options.js b/frontend/src/metabase/parameters/utils/mapping-options.js
index e6d3061166784207625b5098b3bbefd984f6a0cf..62b1de90db78c5a6684e2746b414844e1f9b2ea1 100644
--- a/frontend/src/metabase/parameters/utils/mapping-options.js
+++ b/frontend/src/metabase/parameters/utils/mapping-options.js
@@ -1,5 +1,5 @@
-import { isActionButtonCard } from "metabase/writeback/utils";
 import { tag_names } from "cljs/metabase.shared.parameters.parameters";
+import { isActionButtonCard } from "metabase/writeback/utils";
 import Question from "metabase-lib/lib/Question";
 import { ExpressionDimension } from "metabase-lib/lib/Dimension";
 
diff --git a/frontend/src/metabase/visualizations/visualizations/Text/Text.jsx b/frontend/src/metabase/visualizations/visualizations/Text/Text.jsx
index 9fb9dcafbb19bf41b464396a9c1d3f3ecdd7aae2..917407ecb60583c984a84bbdcf3b1895905c710b 100644
--- a/frontend/src/metabase/visualizations/visualizations/Text/Text.jsx
+++ b/frontend/src/metabase/visualizations/visualizations/Text/Text.jsx
@@ -7,9 +7,9 @@ import _ from "underscore";
 import cx from "classnames";
 import { t } from "ttag";
 
+import { substitute_tags } from "cljs/metabase.shared.parameters.parameters";
 import { withInstanceLanguage, siteLocale } from "metabase/lib/i18n";
 
-import { substitute_tags } from "cljs/metabase.shared.parameters.parameters";
 import styles from "./Text.css";
 
 const getSettingsStyle = settings => ({
diff --git a/frontend/test/metabase-lib/lib/Dimension.unit.spec.js b/frontend/test/metabase-lib/lib/Dimension.unit.spec.js
index 390e1e93001f548ebfcb2985278652e4f76cdedc..92eacdee6410675445138ce066aea505ec6dc60c 100644
--- a/frontend/test/metabase-lib/lib/Dimension.unit.spec.js
+++ b/frontend/test/metabase-lib/lib/Dimension.unit.spec.js
@@ -13,7 +13,7 @@ import Field from "metabase-lib/lib/metadata/Field";
 import StructuredQuery from "metabase-lib/lib/queries/StructuredQuery";
 import NativeQuery from "metabase-lib/lib/queries/NativeQuery";
 import Question from "metabase-lib/lib/Question";
-import { TemplateTagVariable } from "metabase-lib/lib/Variable";
+import TemplateTagVariable from "metabase-lib/lib/variables/TemplateTagVariable";
 
 const nestedQuestionCard = {
   table_id: null,