diff --git a/frontend/src/metabase/lib/expressions/typeinferencer.js b/frontend/src/metabase/lib/expressions/typeinferencer.js
index 10e82feca3ab48c3afd8971b5b718c98286f5caa..85b359e7bcb6ea67890676c9ad092ca7102e2923 100644
--- a/frontend/src/metabase/lib/expressions/typeinferencer.js
+++ b/frontend/src/metabase/lib/expressions/typeinferencer.js
@@ -32,9 +32,16 @@ export function infer(mbql, env) {
       return MONOTYPE.Boolean;
   }
 
-  if (op === "case" || op === "coalesce") {
-    // TODO
-    return MONOTYPE.Undefined;
+  if (op === "case") {
+    const clauses = mbql[1];
+    const first = clauses[0];
+    // TODO: type-checker must ensure the consistent types of all clauses.
+    return infer(first[1], env);
+  }
+
+  if (op === "coalesce") {
+    // TODO: type-checker must ensure the consistent types of all arguments
+    return infer(mbql[1], env);
   }
 
   const func = MBQL_CLAUSES[op];
diff --git a/frontend/test/metabase/lib/expressions/typeinferencer.unit.spec.js b/frontend/test/metabase/lib/expressions/typeinferencer.unit.spec.js
index 985723442be49cb638dab87f8a2098973765b646..95e160557f438eae2bbf43e97748b182daed9153 100644
--- a/frontend/test/metabase/lib/expressions/typeinferencer.unit.spec.js
+++ b/frontend/test/metabase/lib/expressions/typeinferencer.unit.spec.js
@@ -27,10 +27,13 @@ describe("metabase/lib/expressions/typeinferencer", () => {
       case "Price":
         return "number";
       case "FirstName":
+      case "LastName":
         return "string";
       case "BirthDate":
+      case "MiscDate":
         return "type/Temporal";
       case "Location":
+      case "Place":
         return "type/Coordinate";
     }
   }
@@ -92,9 +95,18 @@ describe("metabase/lib/expressions/typeinferencer", () => {
     expect(type("[Location]")).toEqual("type/Coordinate");
   });
 
-  it.skip("should infer the result of CASE", () => {
+  it("should infer the result of CASE", () => {
     expect(type("CASE([X], 1, 2)")).toEqual("number");
     expect(type("CASE([Y], 'this', 'that')")).toEqual("string");
-    expect(type("CASE(BigSale, Price>100, Price>200)")).toEqual("boolean");
+    expect(type("CASE([Z], [Price]>100, [Price]>200)")).toEqual("boolean");
+    expect(type("CASE([ABC], [FirstName], [LastName])")).toEqual("string");
+    expect(type("CASE([F], [BirthDate], [MiscDate])")).toEqual("type/Temporal");
+  });
+
+  it("should infer the result of COALESCE", () => {
+    expect(type("COALESCE([Price])")).toEqual("number");
+    expect(type("COALESCE([FirstName], [LastName])")).toEqual("string");
+    expect(type("COALESCE([BirthDate], [MiscDate])")).toEqual("type/Temporal");
+    expect(type("COALESCE([Place], [Location])")).toEqual("type/Coordinate");
   });
 });
diff --git a/frontend/test/metabase/scenarios/question/custom_column.cy.spec.js b/frontend/test/metabase/scenarios/question/custom_column.cy.spec.js
index dc77ff4648efab7dab44e657f95a83eaa4de530d..e1f128aff1da0542ff724248bc544a488940425f 100644
--- a/frontend/test/metabase/scenarios/question/custom_column.cy.spec.js
+++ b/frontend/test/metabase/scenarios/question/custom_column.cy.spec.js
@@ -453,6 +453,48 @@ describe("scenarios > question > custom columns", () => {
       cy.findByText("Previous");
       cy.findByText("Days");
     });
+
+    it("should handle CASE", () => {
+      openOrdersTable({ mode: "notebook" });
+      cy.findByText("Custom column").click();
+      popover().within(() => {
+        cy.get("[contenteditable='true']")
+          .type("case([Discount] > 0, [Created At], [Product → Created At])")
+          .blur();
+        cy.findByPlaceholderText("Something nice and descriptive").type(
+          "MiscDate",
+        );
+        cy.findByRole("button", { name: "Done" }).click();
+      });
+      cy.findByText("Filter").click();
+      popover()
+        .findByText("MiscDate")
+        .click();
+      cy.findByPlaceholderText("Enter a number").should("not.exist");
+      cy.findByText("Previous");
+      cy.findByText("Days");
+    });
+
+    it("should handle COALESCE", () => {
+      openOrdersTable({ mode: "notebook" });
+      cy.findByText("Custom column").click();
+      popover().within(() => {
+        cy.get("[contenteditable='true']")
+          .type("COALESCE([Product → Created At], [Created At])")
+          .blur();
+        cy.findByPlaceholderText("Something nice and descriptive").type(
+          "MiscDate",
+        );
+        cy.findByRole("button", { name: "Done" }).click();
+      });
+      cy.findByText("Filter").click();
+      popover()
+        .findByText("MiscDate")
+        .click();
+      cy.findByPlaceholderText("Enter a number").should("not.exist");
+      cy.findByText("Previous");
+      cy.findByText("Days");
+    });
   });
 
   it("should handle using `case()` when referencing the same column names (metabase#14854)", () => {