From a13e72fcfa6f8cab5c48402da020ff6168646a5e Mon Sep 17 00:00:00 2001
From: Ben Christel <benchristel@khanacademy.org>
Date: Thu, 16 Jan 2025 13:58:55 -0800
Subject: [PATCH 1/3] [benc/categorizer-options-type] Make 'values' optional on
 categorizer widget options

---
 packages/perseus-core/src/data-schema.ts      |  2 +-
 .../perseus/src/util/extract-perseus-data.ts  |  6 ++--
 .../categorizer-widget.test.ts                | 33 +++++++++++++++++++
 .../perseus-parsers/categorizer-widget.ts     |  2 +-
 .../src/widgets/categorizer/categorizer.tsx   |  5 ++-
 5 files changed, 40 insertions(+), 8 deletions(-)
 create mode 100644 packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.test.ts

diff --git a/packages/perseus-core/src/data-schema.ts b/packages/perseus-core/src/data-schema.ts
index 32d5d3a03b..5bf5ac6c81 100644
--- a/packages/perseus-core/src/data-schema.ts
+++ b/packages/perseus-core/src/data-schema.ts
@@ -423,7 +423,7 @@ export type PerseusCategorizerWidgetOptions = {
     // Whether this widget is displayed with the results and immutable
     static: boolean;
     // The correct answers where index relates to the items and value relates to the category.  e.g. [0, 1, 0, 1, 2]
-    values: ReadonlyArray<number>;
+    values?: ReadonlyArray<number>;
     // Whether we should highlight i18n linter errors found on this widget
     highlightLint?: boolean;
     // Internal editor configuration. Can be ignored by consumers.
diff --git a/packages/perseus/src/util/extract-perseus-data.ts b/packages/perseus/src/util/extract-perseus-data.ts
index 829bbf3032..43d4156259 100644
--- a/packages/perseus/src/util/extract-perseus-data.ts
+++ b/packages/perseus/src/util/extract-perseus-data.ts
@@ -59,9 +59,9 @@ function getAnswersFromWidgets(
                     categorizer.options?.items &&
                     categorizer.options?.values
                 ) {
-                    const categories = categorizer.options?.categories;
-                    const items = categorizer.options?.items;
-                    const values = categorizer.options?.values;
+                    const categories = categorizer.options.categories;
+                    const items = categorizer.options.items;
+                    const values = categorizer.options.values;
                     answers.push(
                         ...values.map(
                             (value, index) =>
diff --git a/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.test.ts b/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.test.ts
new file mode 100644
index 0000000000..93fb551747
--- /dev/null
+++ b/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.test.ts
@@ -0,0 +1,33 @@
+import {
+    CategorizerWidget,
+    PerseusLinterContext
+} from "@khanacademy/perseus-core";
+import {parseCategorizerWidget} from "./categorizer-widget";
+import {success} from "../result";
+import {parse} from "../parse";
+
+describe("parseCategorizerWidget", () => {
+    const baseWidget: CategorizerWidget = {
+        type: "categorizer",
+        version: {major: 0, minor: 0},
+        graded: true,
+        options: {
+            items: [],
+            categories: [],
+            randomizeItems: false,
+            static: false,
+        }
+    }
+
+    it("allows `values` to be undefined", () => {
+        const widget = {
+            ...baseWidget,
+            options: {
+                ...baseWidget.options,
+                values: undefined,
+            },
+        };
+        const result = parse(widget, parseCategorizerWidget);
+        expect(result).toEqual(success(widget))
+    });
+})
diff --git a/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.ts b/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.ts
index f436848306..2a649b0e78 100644
--- a/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.ts
+++ b/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.ts
@@ -21,7 +21,7 @@ export const parseCategorizerWidget: Parser<CategorizerWidget> = parseWidget(
         categories: array(string),
         randomizeItems: defaulted(boolean, () => false),
         static: defaulted(boolean, () => false),
-        values: array(defaulted(number, () => 0)),
+        values: optional(array(defaulted(number, () => 0))),
         highlightLint: optional(boolean),
         linterContext: optional(
             object({
diff --git a/packages/perseus/src/widgets/categorizer/categorizer.tsx b/packages/perseus/src/widgets/categorizer/categorizer.tsx
index ab4c47e366..fd77de05c5 100644
--- a/packages/perseus/src/widgets/categorizer/categorizer.tsx
+++ b/packages/perseus/src/widgets/categorizer/categorizer.tsx
@@ -28,13 +28,13 @@ import type {CategorizerPromptJSON} from "../../widget-ai-utils/categorizer/cate
 import type {PerseusCategorizerWidgetOptions} from "@khanacademy/perseus-core";
 
 type Props = WidgetProps<RenderProps, PerseusCategorizerScoringData> & {
-    values: ReadonlyArray<string>;
+    values: ReadonlyArray<number>;
 };
 
 type DefaultProps = {
     items: Props["items"];
     categories: Props["categories"];
-    values: Props["values"];
+    values: ReadonlyArray<number>;
     linterContext: Props["linterContext"];
 };
 
@@ -79,7 +79,6 @@ export class Categorizer
 
     onChange(itemNum, catNum) {
         const values = [...this.props.values];
-        // @ts-expect-error - TS2322 - Type 'number' is not assignable to type 'never'.
         values[itemNum] = catNum;
         this.change("values", values);
         this.props.trackInteraction();

From 780a8b87a4ae06f912575af74cb45c6b17607b77 Mon Sep 17 00:00:00 2001
From: Ben Christel <benchristel@khanacademy.org>
Date: Thu, 16 Jan 2025 14:03:15 -0800
Subject: [PATCH 2/3] [benc/categorizer-options-type] docs(changeset): Make
 'values' field optional on the PerseusCategorizerWidgetOptions type. This
 will allow us to remove `

---
 .changeset/witty-suns-mate.md | 6 ++++++
 1 file changed, 6 insertions(+)
 create mode 100644 .changeset/witty-suns-mate.md

diff --git a/.changeset/witty-suns-mate.md b/.changeset/witty-suns-mate.md
new file mode 100644
index 0000000000..c2440edd67
--- /dev/null
+++ b/.changeset/witty-suns-mate.md
@@ -0,0 +1,6 @@
+---
+"@khanacademy/perseus": minor
+"@khanacademy/perseus-core": minor
+---
+
+Make `values` field optional on the `PerseusCategorizerWidgetOptions` type. This will allow us to remove `values` (which represents the correct answer) from the data sent to the client.

From e0885be884be1cafc01b63526960cc4b615a3523 Mon Sep 17 00:00:00 2001
From: Ben Christel <benchristel@khanacademy.org>
Date: Thu, 16 Jan 2025 14:08:00 -0800
Subject: [PATCH 3/3] [benc/categorizer-options-type] Fix lint

---
 .../categorizer-widget.test.ts                | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.test.ts b/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.test.ts
index 93fb551747..9f04bd1116 100644
--- a/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.test.ts
+++ b/packages/perseus/src/util/parse-perseus-json/perseus-parsers/categorizer-widget.test.ts
@@ -1,10 +1,9 @@
-import {
-    CategorizerWidget,
-    PerseusLinterContext
-} from "@khanacademy/perseus-core";
-import {parseCategorizerWidget} from "./categorizer-widget";
-import {success} from "../result";
 import {parse} from "../parse";
+import {success} from "../result";
+
+import {parseCategorizerWidget} from "./categorizer-widget";
+
+import type {CategorizerWidget} from "@khanacademy/perseus-core";
 
 describe("parseCategorizerWidget", () => {
     const baseWidget: CategorizerWidget = {
@@ -16,8 +15,8 @@ describe("parseCategorizerWidget", () => {
             categories: [],
             randomizeItems: false,
             static: false,
-        }
-    }
+        },
+    };
 
     it("allows `values` to be undefined", () => {
         const widget = {
@@ -28,6 +27,6 @@ describe("parseCategorizerWidget", () => {
             },
         };
         const result = parse(widget, parseCategorizerWidget);
-        expect(result).toEqual(success(widget))
+        expect(result).toEqual(success(widget));
     });
-})
+});