From 06c53d613e20daffdfbebaa09d4c120bddaff977 Mon Sep 17 00:00:00 2001 From: Mikael Siidorow Date: Mon, 7 Apr 2025 16:19:12 +0300 Subject: [PATCH 1/2] feat(macro): make select macro choices strictly typed --- .../src/macroJsAst.test.ts | 29 ++++++++++++++++ .../src/macroJsAst.ts | 2 ++ .../src/macroJsx.test.ts | 28 +++++++++++++++ .../babel-plugin-lingui-macro/src/macroJsx.ts | 2 ++ .../core/macro/__typetests__/index.test-d.tsx | 34 ++++++++++++++++++- packages/core/macro/index.d.ts | 19 ++++++++--- .../macro/__typetests__/index.test-d.tsx | 19 +++++++++-- packages/react/macro/index.d.ts | 25 +++++++++++--- 8 files changed, 144 insertions(+), 14 deletions(-) diff --git a/packages/babel-plugin-lingui-macro/src/macroJsAst.test.ts b/packages/babel-plugin-lingui-macro/src/macroJsAst.test.ts index 3bf9464ab..850038a82 100644 --- a/packages/babel-plugin-lingui-macro/src/macroJsAst.test.ts +++ b/packages/babel-plugin-lingui-macro/src/macroJsAst.test.ts @@ -372,5 +372,34 @@ describe("js macro", () => { }, }) }) + + it("select without other", () => { + const exp = parseExpression( + `select(gender, { + male: "he", + female: "she", + })` + ) + const tokens = tokenizeChoiceComponent( + (exp as NodePath).node, + JsMacroName.select, + createMacroCtx() + ) + expect(tokens).toMatchObject({ + format: "select", + name: "gender", + options: expect.objectContaining({ + female: "she", + male: "he", + offset: undefined, + other: "", // <- other should be filled with empty string + }), + type: "arg", + value: { + name: "gender", + type: "Identifier", + }, + }) + }) }) }) diff --git a/packages/babel-plugin-lingui-macro/src/macroJsAst.ts b/packages/babel-plugin-lingui-macro/src/macroJsAst.ts index f1bad5ba7..2baf7581d 100644 --- a/packages/babel-plugin-lingui-macro/src/macroJsAst.ts +++ b/packages/babel-plugin-lingui-macro/src/macroJsAst.ts @@ -180,6 +180,8 @@ export function tokenizeChoiceComponent( format: format, options: { offset: undefined, + /** Default to fill other with empty value for compatibility with ICU spec */ + other: "", }, } diff --git a/packages/babel-plugin-lingui-macro/src/macroJsx.test.ts b/packages/babel-plugin-lingui-macro/src/macroJsx.test.ts index a3a746396..6116775ea 100644 --- a/packages/babel-plugin-lingui-macro/src/macroJsx.test.ts +++ b/packages/babel-plugin-lingui-macro/src/macroJsx.test.ts @@ -322,5 +322,33 @@ describe("jsx macro", () => { }, }) }) + + it("Select without other", () => { + const macro = createMacro() + const exp = parseExpression( + ` -// @ts-expect-error: `other` required -m = + +// @ts-expect-error: `other` required unless exhaustive +m = + +// non-exhaustive okay if other is defined +m = // @ts-expect-error: `value` required m =