From 6b809509c43f23edb7a6e8e54d834894e9be2421 Mon Sep 17 00:00:00 2001 From: Fabien Drault Date: Tue, 6 Aug 2024 12:30:07 +0200 Subject: [PATCH] feat(typegen): Intersect type when rules overlap instead of extending. --- .../generate-template-data.test.ts | 2 +- src/translation/generate-template-data.ts | 19 ++++++++++++++----- src/translation/set.ts | 19 +++++++++++++++++++ 3 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 src/translation/set.ts diff --git a/src/translation/generate-template-data.test.ts b/src/translation/generate-template-data.test.ts index 7ac6b2e..d2b4cf5 100644 --- a/src/translation/generate-template-data.test.ts +++ b/src/translation/generate-template-data.test.ts @@ -108,7 +108,7 @@ describe("generateType", () => { expect(result[0]).toMatchObject({ key: "day", interpolations: [ - { name: "count", type: [{ value: "number" }, { value: "string" }] }, + { name: "count", type: [{ value: "number" }] }, { name: "mood", type: [{ value: "string" }] }, { name: "moods", type: [{ value: "string" }] }, ], diff --git a/src/translation/generate-template-data.ts b/src/translation/generate-template-data.ts index b4c720a..070ff4c 100644 --- a/src/translation/generate-template-data.ts +++ b/src/translation/generate-template-data.ts @@ -5,6 +5,7 @@ import { InterpolationTypeTemplateData, TranslationEntryTemplateData, } from "../templates/template-type"; +import { intersection } from "./set"; type TranslationKey = string; type Translation = string; @@ -51,8 +52,8 @@ function toTemplateData(entries: TranslationEntry[]): TranslationEntryTemplateDa const existingInterpolation = interpolations.find((interpol) => interpol.name === name); if (existingInterpolation) { - // Merge types if the interpolation already exists - existingInterpolation.type = mergeUniqueTypes(existingInterpolation.type, types); + // Intersect types if the interpolation already exists to provide the stricter type + existingInterpolation.type = intersectTypes(existingInterpolation.type, types); } else { // Add new interpolation interpolations.push({ @@ -85,12 +86,20 @@ function toTemplateData(entries: TranslationEntry[]): TranslationEntryTemplateDa return Array.from(entryMap.values()); } -function mergeUniqueTypes( +function intersectTypes( existingTypes: InterpolationTypeTemplateData[], newTypes: string[] ): InterpolationTypeTemplateData[] { - const existingTypeValues = new Set([...existingTypes.map((t) => t.value), ...newTypes]); - return Array.from(existingTypeValues).map((it) => ({ value: it })); + const current = new Set(...existingTypes.map((t) => t.value)); + const other = new Set(newTypes); + + const intersect = intersection(current, other); + if (intersect.size > 0) { + return Array.from(intersect).map((it) => ({ value: it })); + } else { + // if not types are in common, the type is defined by the first encountered rule. + return existingTypes; + } } function processTranslation( diff --git a/src/translation/set.ts b/src/translation/set.ts new file mode 100644 index 0000000..aef7425 --- /dev/null +++ b/src/translation/set.ts @@ -0,0 +1,19 @@ +export function intersection(current: Set, other: Set) { + const result = new Set(); + + if (current.size > other.size) { + for (const it of current) { + if (other.has(it)) { + result.add(it); + } + } + } else { + for (const it of other) { + if (current.has(it)) { + result.add(it); + } + } + } + + return result; +}