From 9bf4c9f92609177b37ebc157dfc0d819e5eac995 Mon Sep 17 00:00:00 2001 From: Rebecca Stevens Date: Sat, 12 Aug 2023 00:21:42 +1200 Subject: [PATCH] fix: improve core unit and prefix logic --- scripts/generate-files.ts | 4 +- src/core.ts | 139 +++++++++++++++++++++++++++++++------- 2 files changed, 118 insertions(+), 25 deletions(-) diff --git a/scripts/generate-files.ts b/scripts/generate-files.ts index f2884f2d..3db6b10c 100644 --- a/scripts/generate-files.ts +++ b/scripts/generate-files.ts @@ -64,14 +64,14 @@ function generateExponentsFile() { } function generateSiUnitPrefixesFile() { - const imports = `import { type Multiply, type Unit, type UnknownUnit } from "#uom-types";\n\n`; + const imports = `import { type Multiply, type UnknownUnit, type UnitConversionRate } from "#uom-types";\n\n`; const main = [...exponents.values()] .map((exponent) => { const name = scalar10ToName.get(exponent); if (name === undefined) { return null; } - return `/**\n * Binary prefix denoting an order of magnitude of 10^${exponent}.\n *\n * @group Modifiers\n * @category Metric Prefixes\n */\nexport type ${name} = Multiply>;`; + return `/**\n * Binary prefix denoting an order of magnitude of 10^${exponent}.\n *\n * @group Modifiers\n * @category Metric Prefixes\n */\nexport type ${name} = Multiply>;`; }) .filter(isNotNull) .join("\n\n"); diff --git a/src/core.ts b/src/core.ts index 6e71aeb8..4420f17e 100644 --- a/src/core.ts +++ b/src/core.ts @@ -1,5 +1,5 @@ // eslint-disable-next-line import/no-extraneous-dependencies -import { assert, type Extends } from "tsafe"; +import { assert, type Equals, type Extends } from "tsafe"; import { type Exponent } from "./exponents"; import { type RemoveNeverValues, type ExcludeUnitZeroSubvalues } from "./utils"; @@ -47,7 +47,7 @@ export type UnitFrom< M extends UnknownUnitMeta = UnitMeta<{}>, > = C extends UnitClass ? M extends UnitMeta - ? Unit + ? Unit : never : never; @@ -68,9 +68,7 @@ export type UnitConversionRate = number & { * @group Unit Generators */ export type UnitConversionRateFrom = - M extends UnitMeta - ? UnitConversionRate - : never; + M extends UnitMeta ? UnitConversionRate : never; /** * Used to determine what a unit is of. For example, length, volume, mass etc. @@ -156,23 +154,118 @@ type UnknownUnitKeyValues = { export type UnitSubvalues = Record; // Tests -// eslint-disable-next-line functional/no-conditional-statements if (import.meta.vitest !== undefined) { - assert, UnknownUnit>>(); - assert, UnknownAbstractUnit>>(); - assert, UnknownUnitClass>>(); - assert, UnknownUnitMeta>>(); - assert, UnknownUnitKeyValues>>(); - - assert, UnknownUnit>>(); - assert, UnknownAbstractUnit>>(); - assert, UnknownUnitClass>>(); - assert, UnknownUnitMeta>>(); - assert, UnknownUnitKeyValues>>(); - - assert, UnknownUnit>>(); - assert, UnknownAbstractUnit>>(); - assert, UnknownUnitClass>>(); - assert, UnknownUnitMeta>>(); - assert, UnknownUnitKeyValues>>(); + const { describe, it } = import.meta.vitest; + + describe("Unit", () => { + it("is equivalent to UnitFrom", () => { + assert, UnitFrom>>>(); + assert, UnitFrom>>>(); + assert, UnitFrom>>>(); + }); + }); + + describe("AbstractUnit", () => { + it("a super type of Unit", () => { + assert, AbstractUnit<{}>>>(); + assert, AbstractUnit<{ a: 1 }>>>(); + assert, AbstractUnit>>(); + assert< + Extends>, AbstractUnitFrom>> + >(); + assert< + Extends< + UnitFrom>, + AbstractUnitFrom> + > + >(); + assert< + Extends< + UnitFrom>, + AbstractUnitFrom> + > + >(); + }); + }); + + describe("UnitConversionRate", () => { + it("a super type of Unit", () => { + assert, UnitConversionRate<{}>>>(); + assert, UnitConversionRate<{ a: 1 }>>>(); + assert< + Extends, UnitConversionRate> + >(); + assert< + Extends>, UnitConversionRateFrom>> + >(); + assert< + Extends< + UnitFrom, UnitMeta<{ a: 1 }>>, + UnitConversionRateFrom> + > + >(); + assert< + Extends< + UnitFrom, UnitMeta>, + UnitConversionRateFrom> + > + >(); + }); + }); + + describe("Unknown", () => { + const assignableToConcreteTypes = "is assignable to concrete types"; + + describe("Unit", () => { + it(assignableToConcreteTypes, () => { + assert, UnknownUnit>>(); + assert, UnknownUnit>>(); + assert, UnknownUnit>>(); + }); + }); + + describe("AbstractUnit", () => { + it(assignableToConcreteTypes, () => { + assert, UnknownAbstractUnit>>(); + assert, UnknownAbstractUnit>>(); + assert, UnknownAbstractUnit>>(); + }); + }); + + describe("UnitConversionRate", () => { + it(assignableToConcreteTypes, () => { + assert, UnknownUnitConversionRate>>(); + assert< + Extends, UnknownUnitConversionRate> + >(); + assert< + Extends, UnknownUnitConversionRate> + >(); + }); + }); + + describe("UnitClass", () => { + it(assignableToConcreteTypes, () => { + assert, UnknownUnitClass>>(); + assert, UnknownUnitClass>>(); + assert, UnknownUnitClass>>(); + }); + }); + + describe("UnitMeta", () => { + it(assignableToConcreteTypes, () => { + assert, UnknownUnitMeta>>(); + assert, UnknownUnitMeta>>(); + assert, UnknownUnitMeta>>(); + }); + }); + + describe("UnitKeyValues", () => { + it(assignableToConcreteTypes, () => { + assert, UnknownUnitKeyValues>>(); + assert, UnknownUnitKeyValues>>(); + assert, UnknownUnitKeyValues>>(); + }); + }); + }); }