Home > Software design >  How to type a router with TypeScript
How to type a router with TypeScript

Time:11-16

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]
  • Related