diff --git a/src/data/stages.derived.ts b/src/data/stages.derived.ts index 589e451..f5cf116 100644 --- a/src/data/stages.derived.ts +++ b/src/data/stages.derived.ts @@ -2,18 +2,18 @@ // It contains mainly the support types and values that are derived from // the manually entered values. +import defineOrderFor from "../types/defineOrder"; import { NeverForEmpty } from "../types/NeverForEmpty"; -import { TuplifyUnionAnyOrder } from "../types/unionToTuple"; import { bridgedChains, stages } from "./stages"; export type Stages = typeof stages; export type StageId = keyof Stages; -export type StageIdsOrder = TuplifyUnionAnyOrder; +export const defineStageIdsOrder = defineOrderFor(); export type BridgedChains = typeof bridgedChains; export type BridgedChainId = NeverForEmpty; -export type BridgedChainIdsOrder = TuplifyUnionAnyOrder; +export const defineBridgedChainIdsOrder = defineOrderFor(); diff --git a/src/data/stages.ts b/src/data/stages.ts index 9bd7148..50116b2 100644 --- a/src/data/stages.ts +++ b/src/data/stages.ts @@ -1,4 +1,8 @@ -import { BridgedChainIdsOrder, StageId, StageIdsOrder } from "./stages.derived"; +import { + StageId, + defineStageIdsOrder, + defineBridgedChainIdsOrder, +} from "./stages.derived"; import { BridgedChainsShape, StagesShape } from "./stages.internal"; // Wait for announcements! @@ -149,12 +153,9 @@ export const stages = { export const mainStageId = "mainnet" as const satisfies StageId; -export const stagesDisplayOrder = [ - "mainnet", - "testnet5", -] as const satisfies StageIdsOrder; +export const stagesDisplayOrder = defineStageIdsOrder(["mainnet", "testnet5"]); -export const bridgedChainsDisplayOrder = [ +export const bridgedChainsDisplayOrder = defineBridgedChainIdsOrder([ "avalanche", "base", "filecoin", @@ -163,4 +164,4 @@ export const bridgedChainsDisplayOrder = [ "hyperliquid", "story", "janction", -] as const satisfies BridgedChainIdsOrder; +]); diff --git a/src/types/IsExactPermutation.ts b/src/types/IsExactPermutation.ts new file mode 100644 index 0000000..fc625b8 --- /dev/null +++ b/src/types/IsExactPermutation.ts @@ -0,0 +1,23 @@ +// Checks whether a tuple T contains only unique items. +type IsUnique = T extends readonly [ + infer F, + ...infer R, +] + ? F extends R[number] + ? false + : IsUnique + : true; + +// Checks that T is an exact permutation of U (i.e. it contains each element of U exactly once). +type IsExactPermutation = + // First check that the union of T’s elements equals U. + [T[number]] extends [U] + ? [U] extends [T[number]] + ? // Then check that T has no duplicates. + IsUnique extends true + ? T + : never + : never + : never; + +export default IsExactPermutation; diff --git a/src/types/defineOrder.ts b/src/types/defineOrder.ts new file mode 100644 index 0000000..6cead40 --- /dev/null +++ b/src/types/defineOrder.ts @@ -0,0 +1,7 @@ +import IsExactPermutation from "./IsExactPermutation"; + +function defineOrderFor() { + return (order: IsExactPermutation) => order; +} + +export default defineOrderFor; diff --git a/src/types/unionToTuple.ts b/src/types/unionToTuple.ts deleted file mode 100644 index 7a5be3b..0000000 --- a/src/types/unionToTuple.ts +++ /dev/null @@ -1,32 +0,0 @@ -// Fixed order. - -type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ( - k: infer I, -) => void - ? I - : never; - -type LastOf = - UnionToIntersection T : never> extends () => infer R - ? R - : never; - -type Push = [...T, V]; - -export type TuplifyUnionFixedOrder< - T, - L = LastOf, - N = [T] extends [never] ? true : false, -> = true extends N ? [] : Push>, L>; - -// Any order. - -type TuplifyUnionAnyOrderRecurse = { - [S in U]: Exclude extends never - ? [S] - : [...TuplifyUnionAnyOrderRecurse>, S]; -}[U]; - -export type TuplifyUnionAnyOrder = [U] extends [never] - ? [] - : TuplifyUnionAnyOrderRecurse;