diff --git a/src/component.ts b/src/component.ts index 7268ab6d..176a4e18 100644 --- a/src/component.ts +++ b/src/component.ts @@ -10,7 +10,7 @@ export interface VersionedComponentMap extends LatestComponentVersionMap { export type ComponentId = keyof VersionedComponentMap extends never ? string : keyof VersionedComponentMap; -export type ComponentVersion = Version; +export type ComponentVersion = Version; export type ComponentVersionId = CanonicalVersionId; diff --git a/src/slot.ts b/src/slot.ts index aaaa6492..5cfee043 100644 --- a/src/slot.ts +++ b/src/slot.ts @@ -36,7 +36,7 @@ export type DynamicSlotId = any; export type SlotId = keyof VersionedSlotMap extends never ? string : keyof VersionedSlotMap; -export type SlotVersion = Version; +export type SlotVersion = Version; export type SlotVersionId = CanonicalVersionId; diff --git a/src/versioning.ts b/src/versioning.ts index 980c3d05..52c93ccf 100644 --- a/src/versioning.ts +++ b/src/versioning.ts @@ -2,10 +2,6 @@ import {JsonObject} from '@croct/json'; export type LatestAlias = 'latest'; -export type ExtractVersion = I extends `${string}@${infer V}` - ? (LatestAlias extends V ? LatestAlias : (V extends `${number}` ? V : never)) - : LatestAlias; - export type CanonicalVersionId = { [K in I]: `${K}@${Extract, `${number}`>}` }[I]; @@ -17,13 +13,26 @@ type CastString = T extends `${infer V}` ? V : string; export type VersionedId = CastString | {[K in I]: `${K}@${Version & string}`}[I]; -export type ExtractId = I extends `${infer V}@${string}` ? V : CastString; - export type Version = LatestAlias | (I extends keyof M ? keyof M[I] : never); +type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never; + +type Expand = {[K in keyof T]: T[K]}; + +type FlattenVersionMap = Expand< + UnionToIntersection< + { + [K in Extract]: { + [K2 in Extract as (`${K}@${K2}` | (LatestAlias extends K2 ? K : never))]: T[K][K2]; + } + }[Extract] + > +>; + export type Versioned = - ExtractId extends keyof M - ? ExtractVersion extends keyof M[ExtractId] - ? M[ExtractId][ExtractVersion] + // Ensure T is string + I extends `${infer K}` + ? K extends keyof FlattenVersionMap + ? FlattenVersionMap[K] : C : C; diff --git a/test/component.test.ts b/test/component.test.ts index 4c133341..3fe58196 100644 --- a/test/component.test.ts +++ b/test/component.test.ts @@ -132,23 +132,11 @@ describe('Component typing', () => { ); }); - it('should export a ComponentVersion type that resolves to "latest" when no component mapping exists', () => { - const code: CodeOptions = { - imports: ['ComponentVersion'], - mapping: false, - type: 'ComponentVersion', - }; - - expect(() => compileCode(code)).not.toThrow(); - - expect(getTypeName(code)).toBe('"latest"'); - }); - it('should export a ComponentVersion that resolves to a union of all component versions', () => { const code: CodeOptions = { imports: ['ComponentVersion'], mapping: true, - type: 'ComponentVersion', + type: 'ComponentVersion<"banner">', }; expect(() => compileCode(code)).not.toThrow(); diff --git a/test/slot.test.ts b/test/slot.test.ts index 07b95e46..f271295f 100644 --- a/test/slot.test.ts +++ b/test/slot.test.ts @@ -178,24 +178,13 @@ describe('Slot typing', () => { ); }); - it('should export a SlotVersion type that resolves to "latest" when no slot mapping exists', () => { - const code: CodeOptions = { - imports: ['SlotVersion'], - type: 'SlotVersion', - }; - - expect(() => compileCode(code)).not.toThrow(); - - expect(getTypeName(code)).toBe('"latest"'); - }); - it('should export a SlotVersion that resolves to a union of all slot versions', () => { const code: CodeOptions = { imports: ['SlotVersion'], mapping: { slot: true, }, - type: 'SlotVersion', + type: 'SlotVersion<"home-banner">', }; expect(() => compileCode(code)).not.toThrow();