diff --git a/frontend/src/metabase-types/types/Parameter.ts b/frontend/src/metabase-types/types/Parameter.ts
index 8f3e8e1778d142c480c21363565144a14277ce4b..fdf8770ad814b6d7d5165cf5903efface7bb28fd 100644
--- a/frontend/src/metabase-types/types/Parameter.ts
+++ b/frontend/src/metabase-types/types/Parameter.ts
@@ -8,7 +8,10 @@ export type ParameterType = string;
 export type VariableTarget = ["template-tag", string];
 export type ParameterVariableTarget = ["variable", VariableTarget];
 export type DimensionTarget = LocalFieldReference | ForeignFieldReference;
-export type ParameterDimensionTarget = ["dimension", DimensionTarget];
+export type ParameterDimensionTarget = [
+  "dimension",
+  DimensionTarget | VariableTarget,
+];
 
 export type ParameterValueOrArray = string | Array<any>;
 
diff --git a/frontend/src/metabase-types/types/Query.ts b/frontend/src/metabase-types/types/Query.ts
index f0df0b0e1b4279e693551b41c5c99469742803c5..9b533783e4f51bf86358e10af1551b5e242c13be 100644
--- a/frontend/src/metabase-types/types/Query.ts
+++ b/frontend/src/metabase-types/types/Query.ts
@@ -47,7 +47,13 @@ export type DatetimeUnit =
 
 export type TemplateTagId = string;
 export type TemplateTagName = string;
-export type TemplateTagType = "card" | "text" | "number" | "date" | "dimension";
+export type TemplateTagType =
+  | "card"
+  | "text"
+  | "number"
+  | "date"
+  | "dimension"
+  | "snippet";
 
 export type TemplateTag = {
   id: TemplateTagId;
diff --git a/frontend/src/metabase/parameters/utils/cards.js b/frontend/src/metabase/parameters/utils/cards.ts
similarity index 60%
rename from frontend/src/metabase/parameters/utils/cards.js
rename to frontend/src/metabase/parameters/utils/cards.ts
index eeee751c6473b8c1ab46a3b53da388d2f0bfb6dc..265bed63523f7755ab9d63e4a3de5703615761f1 100644
--- a/frontend/src/metabase/parameters/utils/cards.js
+++ b/frontend/src/metabase/parameters/utils/cards.ts
@@ -10,35 +10,45 @@ import {
   getValuePopulatedParameters,
   hasParameterValue,
 } from "metabase/parameters/utils/parameter-values";
+import { ParameterWithTarget } from "metabase/parameters/types";
+import { Parameter, ParameterTarget } from "metabase-types/types/Parameter";
+import { Card } from "metabase-types/types/Card";
+import { TemplateTag } from "metabase-types/types/Query";
+import Metadata from "metabase-lib/lib/metadata/Metadata";
 
-// NOTE: this should mirror `template-tag-parameters` in src/metabase/api/embed.clj
-export function getTemplateTagParameters(tags) {
-  function getTemplateTagType(tag) {
-    const { type } = tag;
-    if (type === "date") {
-      return "date/single";
-    } else if (type === "string") {
-      return "string/=";
-    } else if (type === "number") {
-      return "number/=";
-    } else {
-      return "category";
-    }
+function getTemplateTagType(tag: TemplateTag) {
+  const { type } = tag;
+  if (type === "date") {
+    return "date/single";
+    // @ts-expect-error -- preserving preexisting incorrect types (for now)
+  } else if (type === "string") {
+    return "string/=";
+  } else if (type === "number") {
+    return "number/=";
+  } else {
+    return "category";
   }
+}
 
+// NOTE: this should mirror `template-tag-parameters` in src/metabase/api/embed.clj
+export function getTemplateTagParameters(
+  tags: TemplateTag[],
+): ParameterWithTarget[] {
   return tags
     .filter(
       tag =>
         tag.type != null && (tag["widget-type"] || tag.type !== "dimension"),
     )
     .map(tag => {
+      const target: ParameterTarget =
+        tag.type === "dimension"
+          ? ["dimension", ["template-tag", tag.name]]
+          : ["variable", ["template-tag", tag.name]];
+
       return {
         id: tag.id,
         type: tag["widget-type"] || getTemplateTagType(tag),
-        target:
-          tag.type === "dimension"
-            ? ["dimension", ["template-tag", tag.name]]
-            : ["variable", ["template-tag", tag.name]],
+        target,
         name: tag["display-name"],
         slug: tag.name,
         default: tag.default,
@@ -46,21 +56,24 @@ export function getTemplateTagParameters(tags) {
     });
 }
 
-export function getTemplateTagsForParameters(card) {
-  const templateTags =
+export function getTemplateTagsForParameters(card: Card) {
+  const templateTags: TemplateTag[] =
     card &&
     card.dataset_query &&
     card.dataset_query.type === "native" &&
     card.dataset_query.native["template-tags"]
       ? Object.values(card.dataset_query.native["template-tags"])
       : [];
+
   return templateTags.filter(
     // this should only return template tags that define a parameter of the card
     tag => tag.type !== "card" && tag.type !== "snippet",
   );
 }
 
-export function getParametersFromCard(card) {
+export function getParametersFromCard(
+  card: Card,
+): Parameter[] | ParameterWithTarget[] {
   if (card && card.parameters) {
     return card.parameters;
   }
@@ -70,23 +83,25 @@ export function getParametersFromCard(card) {
 }
 
 export function getValueAndFieldIdPopulatedParametersFromCard(
-  card,
-  metadata,
-  parameterValues,
+  card: Card,
+  metadata: Metadata,
+  parameterValues: { [key: string]: any },
 ) {
   if (!card) {
     return [];
   }
 
   const parameters = getParametersFromCard(card);
-  const valuePopulatedParameters = getValuePopulatedParameters(
-    parameters,
-    parameterValues,
-  );
+  const valuePopulatedParameters: (Parameter[] | ParameterWithTarget[]) & {
+    value?: any;
+  } = getValuePopulatedParameters(parameters, parameterValues);
   const question = new Question(card, metadata);
 
   return valuePopulatedParameters.map(parameter => {
-    const field = getParameterTargetField(parameter.target, metadata, question);
+    const target:
+      | ParameterTarget
+      | undefined = (parameter as ParameterWithTarget).target;
+    const field = getParameterTargetField(target, metadata, question);
     return {
       ...parameter,
       fields: field == null ? [] : [field],
@@ -101,11 +116,15 @@ export function getValueAndFieldIdPopulatedParametersFromCard(
 // we need to transform this into a map of template tag ids to parameter values
 // so that we popoulate the template tags in the native editor
 export function remapParameterValuesToTemplateTags(
-  templateTags,
-  dashboardParameters,
-  parameterValuesByDashboardParameterId,
+  templateTags: TemplateTag[],
+  dashboardParameters: ParameterWithTarget[],
+  parameterValuesByDashboardParameterId: {
+    [key: string]: any;
+  },
 ) {
-  const parameterValues = {};
+  const parameterValues: {
+    [key: string]: any;
+  } = {};
   const templateTagParametersByName = _.indexBy(templateTags, "name");
 
   dashboardParameters.forEach(dashboardParameter => {