从映射的对象中获取Typescript类型



我正在尝试执行以下操作:

共享.ts

export type ReverseMap<T> = T[keyof T];
/*
This is where i want to return a slightly modified type with the '/root/' appended to the values.
*/
export const getRoutesForPages = <T>( pages: T, root: string ): T => {
Object.keys(pages).forEach((key) => {
pages[key] = `/${root}/${pages[key]}`
});
return pages;
}

管理员

import { getRoutesForPages, ReverseMap } from './shared';
// root is basically the name of the lazy loaded module.
const ROOT = 'admin';
// pages are referenced by the routes within lazy loaded module
export const PAGES = {
PAGE_1: `p-1`,
PAGE_2: `p-2`,
} as const;
export type Page = ReverseMap<typeof PAGES>;
// gives me a type with 'p-1' and 'p-2'
/* creates a mapped routes object referenced throughout the application
export const ROUTES = {
PAGE_1: `/admin/p-1`,
PAGE_2: `/admin/p-2`,
} as const;
The issue is that it still returns interface of PAGES not the modified.
*/
const ROUTES = getRoutesForPages<typeof PAGES>(PAGES, ROOT);
// should create a type like '/admin/p-1' and 'admin/p-2'
export type Route = ReverseMap<typeof ROUTES>; // create a type from my route object

type Route返回"p-1"one_answers"p-2"。

我希望它返回'/admin/p-1'和'/admin-p-2'作为类型。

理想情况下在getRoutesForPages功能内完成,以便于重新使用。我在泛型和类型方面的经验是有限的,所以希望能提供一些帮助。或者,如果有更好的解决方案,请告诉我。

在函数中添加另一个泛型参数,以推断root参数的类型。然后在返回类型中,您可以使用映射类型并使用泛型参数Root引用root参数。对于模板文字类型,它实际上与您的代码做着相同的事情。

const getRoutesForPages = <T extends Record<any, string>, Root extends string>( pages: T, root: Root ): { [K in keyof T]: `/${Root}/${T[K]}` } => {
pages = { ...pages };
(Object.keys(pages) as (keyof T)[]).forEach((key) => {
pages[key] = `/${root}/${pages[key]}` as T[keyof T]; // technically incorrect cast and only exists to suppress errors
});
return pages as ReturnType<typeof getRoutesForPages<T, Root>>;
};

此外,您的原始代码pages参数进行了突变,这意味着您的PAGES常量实际上发生了更改,这是一个很大的禁忌。这就是为什么我添加了pages = { ...pages };来创建一个我们可以修改的浅拷贝。

您还会注意到正文中的新类型断言。我们在这里做一些恶心的事情,所以我认为最简单的方法就是把它们选对类型。

const ROUTES = getRoutesForPages(PAGES, ROOT);
export type Route = ReverseMap<typeof ROUTES>;

您也不必显式地向函数传递任何泛型,因为TypeScript可以为您推断这些泛型。根据需要,您的Route类型现在是"/admin/p-1" | "/admin/p-2"

游乐场

最新更新