I have a standard router typing.
type Routes = '/' | '/achievements' | ... ;
This allows you to understand which routers are in the project. But now I have the task to make an array containing all the routers.
const allRoutes: Routes[] = ['/', '/achievements'];
If any router is missing, it should get an error. This array must always contain all routers. How can it be done?
I can't figure out how to require the array to contain the entire enumeration of routers.
UPDATE
My types are described in the file d.ts. So I cannot declare the construct
const ROUTES = ['/', '/achievements'] as const
and export it there
CodePudding user response:
You can do it this way:
const ROUTES = ['/', '/achievements'] as const
type RoutesTuple = typeof ROUTES
type Routes = RoutesTuple[number]
const allRoutes: RoutesTuple = ['/', '/achievements']
CodePudding user response:
You may use a function which enforces array to have every item of union type
type Routes = 'a' | 'b' | 'c'
const usedRoutes = ['a', 'b', 'd']
function ensureArrayHasEvery<T>() {
return function <A extends readonly T[]>(a: NoInfer<ArrayWithEvery<A, T>> | A & [never]) {
return a;
}
}
let x = ensureArrayHasEvery<Routes>()
// ^?
let y = x(['a', 'b', "c"])
// ^? ['a']
let z = x(['a'])
// ^? Argument of type '["a"]' is not assignable to parameter of type '["a", "b" | "c"]
type ArrayWithEvery<A extends readonly any[], V> = [V] extends [A[number]] ? A : [...A, Exclude<V, A[number]>]
type NoInfer<A> = [A][A extends any ? 0 : never]