Сопоставьте маршруты angular с типом, ключи которого являются свойствами пути - PullRequest
0 голосов
/ 05 августа 2020

У меня есть такие маршруты

const routes = [
  { path: 'path1' },
  { path: 'path2', children: [{ path: 'path3' }] },
] as const;

, и мне нужна такая карта

type map = { path1: {}; path2: { path3: {} } };

Итак, как я могу исправить тип ниже, чтобы получить карту из маршрут, как указано выше?

type MappedRoutes<TRoutes> = {
  [K in keyof TRoutes]: TRoutes[K] extends {children: unknown, path: string, }
    ? {TRoutes[K]['path']: MappedRoutes<TRoutes[K]['children']>}
    : TRoutes[K]['path'];
}

То есть MappedRoutes<ArrayIndexes<typeof routes>>, как показано ниже, должно возвращаться {path1: {}; path2: { path3: {} } };

const array = [] as const;
type keyOfArray = keyof typeof array;
type ArrayIndexes<TArray> = Exclude<keyof TArray, keyOfArray>;

type mapped= MappedRoutes<ArrayIndexes<typeof routes>>;

1 Ответ

1 голос
/ 05 августа 2020

Я бы, вероятно, написал это так:

type Routes = readonly { path: string, children?: Routes }[];

type MappedRoutes<T extends Routes> = {
    [K in T[number]["path"]]: (Extract<T[number], { path: K }>['children'] extends infer R ?
        R extends Routes ? MappedRoutes<R> extends infer O ? {
            [P in keyof O]: O[P]
        } : never : {} : never)
}

Вы можете проверить, что он работает так, как вы хотите (хотя и без вмешательства ArrayIndices):

type Mapped = MappedRoutes<typeof routes>
/* type Mapped = {
    path1: {};
    path2: {
        path3: {};
    };
} */

Если T присваивается Routes, массиву {path: string, children?: Routes}, тогда MappedRoutes<T> имеет ключи в T[number]["path"] ... где T[number] - это объединение типов элементов массива, а T[number]["path"] - это объединение их свойств path.

Затем для каждого из этих ключей K мы получаем Extract<T[number], {path: K}>['children'], которое является свойством children, соответствующим этому path. (Extract<T[number], {path: K}>) принимает объединение элементов массива и извлекает только тот, который можно присвоить {path: K}. И тогда мы получаем его свойство children).

Мы проверяем это свойство children. Это сам Routes? Если это так, рекурсивно создайте MappedRoutes его. Там происходит изрядное количество условного вывода типов, но в основном для того, чтобы я мог хранить типы в переменных типа, а не переписывать их. R - это свойство children, а O - это сопоставленное свойство children, если оно существует. Я прохожу через O, чтобы тип Mapped быстро рекурсивно расширялся до своей окончательной формы вместо того, чтобы оставить его как {path1: {}, path2: MappedRoutes<readonly blah blah yuck>}.

Хорошо, надеюсь, это поможет; удачи!

Детская площадка ссылка на код

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...