diff --git a/frontend/src/metabase-lib/metadata/Table.unit.spec.ts b/frontend/src/metabase-lib/metadata/Table.unit.spec.ts
index 58ac1aa1eeaa74d7c49d2064aec24158a39ed9cf..1a802d70630fc05ca254033afbcc07d50d5bae6a 100644
--- a/frontend/src/metabase-lib/metadata/Table.unit.spec.ts
+++ b/frontend/src/metabase-lib/metadata/Table.unit.spec.ts
@@ -9,14 +9,16 @@ const TABLE_ORIGIN_ID = 1;
 const TABLE_DESTINATION_ID = 2;
 const TABLE_EMPTY_ID = 3;
 const TABLE_VIRTUAL_ID = "card__1";
+const FIELD_ORIGIN_ID = 1;
+const FIELD_DESTINATION_ID = 2;
 
 const FIELD_ORIGIN = createMockField({
-  id: 1,
+  id: FIELD_ORIGIN_ID,
   table_id: TABLE_ORIGIN_ID,
 });
 
 const FIELD_DESTINATION = createMockField({
-  id: 2,
+  id: FIELD_DESTINATION_ID,
   table_id: TABLE_DESTINATION_ID,
 });
 
@@ -31,9 +33,9 @@ const TABLE_DESTINATION = createMockTable({
   fks: [
     createMockForeignKey({
       origin: FIELD_ORIGIN,
-      origin_id: FIELD_ORIGIN.id,
+      origin_id: FIELD_ORIGIN_ID,
       destination: FIELD_DESTINATION,
-      destination_id: FIELD_DESTINATION.id,
+      destination_id: FIELD_DESTINATION_ID,
     }),
   ],
 });
diff --git a/frontend/src/metabase-lib/metadata/mocks.ts b/frontend/src/metabase-lib/metadata/mocks.ts
deleted file mode 100644
index c62e9e04467e8a205e8e477d476e810f63d21000..0000000000000000000000000000000000000000
--- a/frontend/src/metabase-lib/metadata/mocks.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { createMockField } from "metabase-types/api/mocks/field";
-import { Field as ApiField } from "metabase-types/api";
-import Field from "./Field";
-
-export function createMockConcreteField({
-  apiOpts,
-  instanceOpts,
-}: {
-  apiOpts?: Partial<ApiField>;
-  instanceOpts?: Partial<Field>;
-}) {
-  const mockField = createMockField(apiOpts);
-  const instance = new Field(mockField);
-
-  Object.assign(instance, instanceOpts);
-
-  return instance;
-}
-
-export function createMockVirtualField({
-  constructorOpts,
-  instanceOpts,
-}: {
-  constructorOpts?: Partial<Field>;
-  instanceOpts?: Partial<Field>;
-}) {
-  const instance = new Field(constructorOpts);
-
-  Object.assign(instance, instanceOpts);
-
-  return instance;
-}
diff --git a/frontend/src/metabase-lib/metadata/utils/fields.unit.spec.ts b/frontend/src/metabase-lib/metadata/utils/fields.unit.spec.ts
index d941771f120c1eae9fc37a7849f1551c70d6eb98..abbe9ccb039e0132d168f184a9fcdac4a48a61dd 100644
--- a/frontend/src/metabase-lib/metadata/utils/fields.unit.spec.ts
+++ b/frontend/src/metabase-lib/metadata/utils/fields.unit.spec.ts
@@ -1,62 +1,90 @@
-import { createMockConcreteField, createMockVirtualField } from "../mocks";
+import { FieldReference } from "metabase-types/api";
+import { createMockField, createMockTable } from "metabase-types/api/mocks";
+import { createMockMetadata } from "__support__/metadata";
 import { getUniqueFieldId } from "./fields";
 
-const structuredVirtualCardField = createMockConcreteField({
-  apiOpts: {
-    id: 1,
-    table_id: "card__123",
-    name: "foo",
-  },
+const DB_TABLE_ID = 1;
+const CARD_TABLE_ID = "card__1";
+
+const DB_FIELD_ID = 1;
+const CARD_FIELD_ID = 2;
+const NESTED_DB_FIELD_ID: FieldReference = ["field", 3, null];
+const NATIVE_CARD_FIELD_ID: FieldReference = [
+  "field",
+  "foo",
+  { "base-type": "type/Integer" },
+];
+
+const DB_FIELD = createMockField({
+  id: DB_FIELD_ID,
+  table_id: DB_TABLE_ID,
+  name: "foo",
+  display_name: "foo",
+});
+
+const NESTED_DB_FIELD = createMockField({
+  id: NESTED_DB_FIELD_ID,
 });
 
-const nativeVirtualCardField = createMockConcreteField({
-  apiOpts: {
-    id: undefined,
-    table_id: "card__123",
-    name: "foo",
-  },
+const CARD_FIELD = createMockField({
+  id: CARD_FIELD_ID,
+  table_id: CARD_TABLE_ID,
+  name: "foo",
+  display_name: "foo",
 });
 
-const concreteTableField = createMockConcreteField({
-  apiOpts: {
-    id: 1,
-    table_id: 123,
-    name: "foo",
-  },
+const NATIVE_CARD_FIELD = createMockField({
+  id: NATIVE_CARD_FIELD_ID,
+  table_id: CARD_TABLE_ID,
+  name: "foo",
+  display_name: "foo",
 });
 
-const fieldWithFieldRefId = createMockVirtualField({
-  constructorOpts: {
-    id: ["field", 1, null],
-    table_id: 123,
-  },
+const DB_TABLE = createMockTable({
+  id: DB_TABLE_ID,
+  fields: [DB_FIELD],
 });
 
+const CARD_TABLE = createMockTable({
+  id: CARD_TABLE_ID,
+  fields: [CARD_FIELD, NESTED_DB_FIELD, NATIVE_CARD_FIELD],
+});
+
+const setup = () => {
+  return createMockMetadata({ tables: [DB_TABLE, CARD_TABLE] });
+};
+
 describe("metabase-lib/metadata/utils", () => {
   describe("getUniqueFieldId", () => {
     describe("when the given field is from a concrete table", () => {
       it("should return the field's id", () => {
-        expect(getUniqueFieldId(concreteTableField)).toEqual(1);
+        const metadata = setup();
+        const field = metadata.field(DB_FIELD_ID);
+        expect(field && getUniqueFieldId(field)).toEqual(DB_FIELD_ID);
       });
     });
 
     describe("when the given field is from a structured virtual card table", () => {
       it("should return a combination of the field's id and table_id", () => {
-        expect(getUniqueFieldId(structuredVirtualCardField)).toBe(
-          "card__123:1",
-        );
+        const metadata = setup();
+        const field = metadata.field(CARD_FIELD_ID, CARD_TABLE_ID);
+        expect(field && getUniqueFieldId(field)).toBe("card__1:2");
       });
     });
 
     describe("when the given field is from a native virtual card table", () => {
       it("should return a combination of the field's name and table_id", () => {
-        expect(getUniqueFieldId(nativeVirtualCardField)).toBe("card__123:foo");
+        const metadata = setup();
+        const field = metadata.field(NATIVE_CARD_FIELD_ID, CARD_TABLE_ID);
+        expect(field && getUniqueFieldId(field)).toBe("card__1:foo");
       });
     });
 
     describe("when the given field has a field ref id", () => {
       it("should return the field ref id", () => {
-        expect(getUniqueFieldId(fieldWithFieldRefId)).toBe(1);
+        const metadata = setup();
+        const field = metadata.field(NESTED_DB_FIELD_ID);
+        expect(field && getUniqueFieldId(field)).toBe(NESTED_DB_FIELD_ID[1]);
       });
     });
   });
diff --git a/frontend/src/metabase-lib/metadata/utils/models.ts b/frontend/src/metabase-lib/metadata/utils/models.ts
index e7bd5b572c0250f8ef5ff665c1c8f9d75c4c1f12..102dceb6eef47bb72033a46bb9e174f3fbf05776 100644
--- a/frontend/src/metabase-lib/metadata/utils/models.ts
+++ b/frontend/src/metabase-lib/metadata/utils/models.ts
@@ -6,6 +6,7 @@ import {
   TableColumnOrderSetting,
   TemplateTag,
   StructuredDatasetQuery,
+  FieldId,
 } from "metabase-types/api";
 import { getQuestionVirtualTableId } from "metabase-lib/metadata/utils/saved-questions";
 import Database from "metabase-lib/metadata/Database";
@@ -15,7 +16,7 @@ import { isSameField } from "metabase-lib/queries/utils/field-ref";
 import { isStructured } from "metabase-lib/queries/utils";
 
 type FieldMetadata = {
-  id?: number | string;
+  id?: FieldId | FieldReference;
   name: string;
   display_name: string;
   description?: string | null;
diff --git a/frontend/src/metabase-types/api/field.ts b/frontend/src/metabase-types/api/field.ts
index c67e159824f757cc4d9f1d141bf1f6b7b6803f1b..c3b5a185515519171cf796186a10ed3196b736a5 100644
--- a/frontend/src/metabase-types/api/field.ts
+++ b/frontend/src/metabase-types/api/field.ts
@@ -1,4 +1,5 @@
 import { RowValue } from "./dataset";
+import { FieldReference } from "./query";
 import { Table, TableId } from "./table";
 
 export type FieldId = number;
@@ -65,8 +66,8 @@ export type FieldDimensionOption = {
   type: string;
 };
 
-export interface ConcreteField {
-  id: FieldId;
+export interface Field {
+  id: FieldId | FieldReference;
   table_id: TableId;
   table?: Table;
 
@@ -118,10 +119,6 @@ export interface FieldValues {
   has_more_values: boolean;
 }
 
-export type Field = Omit<ConcreteField, "id"> & {
-  id?: FieldId;
-};
-
 export interface FieldFormattingSettings {
   currency?: string;
 }
diff --git a/frontend/src/metabase/models/containers/ModelDetailPage/ModelDetailPage.unit.spec.tsx b/frontend/src/metabase/models/containers/ModelDetailPage/ModelDetailPage.unit.spec.tsx
index 52f0937330b01ad5aff411025902783ff48757ba..2ebf5dcd9fe1ef01def8a4b481fde963cb9dd061 100644
--- a/frontend/src/metabase/models/containers/ModelDetailPage/ModelDetailPage.unit.spec.tsx
+++ b/frontend/src/metabase/models/containers/ModelDetailPage/ModelDetailPage.unit.spec.tsx
@@ -80,8 +80,9 @@ const TEST_FIELD = createMockField({
 });
 
 const TEST_FK_TABLE_1_ID = 2;
+const TEST_FK_FIELD_ID = 4;
 const TEST_FK_FIELD = createMockField({
-  id: 4,
+  id: TEST_FK_FIELD_ID,
   table_id: TEST_FK_TABLE_1_ID,
 });
 
@@ -97,7 +98,7 @@ const TEST_FIELDS = [
     display_name: "Field 3",
     table_id: TEST_TABLE_ID,
     semantic_type: TYPE.FK,
-    fk_target_field_id: TEST_FK_FIELD.id,
+    fk_target_field_id: TEST_FK_FIELD_ID,
     target: TEST_FK_FIELD,
   }),
 ];
diff --git a/frontend/src/metabase/parameters/utils/formatting.unit.spec.ts b/frontend/src/metabase/parameters/utils/formatting.unit.spec.ts
index 67af9bb52a347bd3df9cdc0bf902e81ffa7463c5..1bb52ac0f6460b75e04aa2caa95407800557e6c6 100644
--- a/frontend/src/metabase/parameters/utils/formatting.unit.spec.ts
+++ b/frontend/src/metabase/parameters/utils/formatting.unit.spec.ts
@@ -1,28 +1,31 @@
 import { createMockMetadata } from "__support__/metadata";
 import { checkNotNull } from "metabase/core/utils/types";
+import { createMockField } from "metabase-types/api/mocks";
 import {
   createSampleDatabase,
   PRODUCTS,
   ORDERS,
 } from "metabase-types/api/mocks/presets";
-
 import { createMockUiParameter } from "metabase-lib/parameters/mock";
-import Field from "metabase-lib/metadata/Field";
 import { formatParameterValue } from "./formatting";
 
+const REMAPPED_FIELD_ID = 100;
+
 const metadata = createMockMetadata({
   databases: [createSampleDatabase()],
+  fields: [
+    createMockField({
+      id: REMAPPED_FIELD_ID,
+      base_type: "type/Text",
+      remappings: [[123456789, "A"]],
+    }),
+  ],
 });
 
 const numberField = checkNotNull(metadata.field(ORDERS.TOTAL));
 const textField = checkNotNull(metadata.field(PRODUCTS.TITLE));
 const categoryField = checkNotNull(metadata.field(PRODUCTS.CATEGORY));
-
-const remappedField = new Field({
-  base_type: "type/Text",
-  human_readable_field_id: numberField.id,
-  remapping: new Map([[123456789, 0]]),
-});
+const remappedField = checkNotNull(metadata.field(REMAPPED_FIELD_ID));
 
 describe("metabase/parameters/utils/formatting", () => {
   describe("formatParameterValue", () => {
@@ -129,7 +132,7 @@ describe("metabase/parameters/utils/formatting", () => {
         type: "number/=",
         fields: [remappedField],
       });
-      expect(formatParameterValue(123456789, parameter)).toEqual(0);
+      expect(formatParameterValue(123456789, parameter)).toEqual("A");
     });
   });
 });
diff --git a/frontend/test/metabase-lib/lib/Dimension.unit.spec.js b/frontend/test/metabase-lib/lib/Dimension.unit.spec.js
index 74ff2ec4c831ad4d58bbfccb6519de72444318ba..24650a42c2df41cdc416698d0de95d425047a129 100644
--- a/frontend/test/metabase-lib/lib/Dimension.unit.spec.js
+++ b/frontend/test/metabase-lib/lib/Dimension.unit.spec.js
@@ -942,14 +942,10 @@ describe("Dimension", () => {
     describe("field", () => {
       it("should return the cached Field instance", () => {
         const category = metadata.field(PRODUCTS.CATEGORY);
-        const fieldFromEndpoint = new Field({
-          ...category.getPlainObject(),
-          _comesFromEndpoint: true,
-        });
 
-        const fieldDimension = fieldFromEndpoint.dimension();
-        expect(fieldDimension._fieldInstance).toBe(fieldFromEndpoint);
-        expect(fieldDimension.field()).toBe(fieldFromEndpoint);
+        const fieldDimension = category.dimension();
+        expect(fieldDimension._fieldInstance).toBe(category);
+        expect(fieldDimension.field()).toBe(category);
       });
     });
   });