我正在try 解决如何修复这个接口,以便每个"Route"可以有一个独立的模板参数,与映射中的其他条目不同:
export type RouteMap = {
[k in string]: Route<any>
}
在这里,我不是真的想指定any
,我希望它是推断的.有没有什么方法可以说每个条目都应该是Route<something>
,但<something>
可以是不同的?
这是一个应该编制的minimal example of TS Playground分.
我正在try 解决如何修复这个接口,以便每个"Route"可以有一个独立的模板参数,与映射中的其他条目不同:
export type RouteMap = {
[k in string]: Route<any>
}
在这里,我不是真的想指定any
,我希望它是推断的.有没有什么方法可以说每个条目都应该是Route<something>
,但<something>
可以是不同的?
这是一个应该编制的minimal example of TS Playground分.
TypeScrip只能推断函数中的泛型类型参数.因此,您可以使用一个只返回其参数的简单函数,同时还使用泛型类型参数约束该参数的类型,以强制TypeScrip执行此类推断:
export type RouteMap<T extends Record<string, any>> = {
[R in keyof T]: Route<T[R]>;
}
// TypeScript can only infer generic types using function parameters
function routeMap<T extends Record<string, any>>(arg: RouteMap<T>) { return arg; }
export interface Route<P extends UriParams> {
template: UriTemplate<P>
get?: Handler<P>
post?: Handler<P>
}
export type UriParams = Record<string, UrlParamValue>;
type Primitive = string | number | boolean | null;
type PrimitivePair = [key: string, value: Primitive];
type PrimitiveMap = {
[K in string]: Primitive;
};
export type UrlParamValue = Primitive | Primitive[] | PrimitivePair[] | PrimitiveMap;
export type Handler<P extends UriParams> = (req: BunRequest<P>, res: HybridResponse) => void | Promise<void>
type HybridResponse = unknown
interface BunRequest<P extends UriParams> {
headers: Headers
method: unknown
url: BunUrl<P>
body: unknown
}
interface BunUrl<P extends UriParams> extends URL {
params: P
path: string
}
export class UriTemplate<P extends UriParams> {
constructor(template: string) {
//
}
}
////////////////////////////////
const routes = routeMap({
hello: {
template: new UriTemplate<{q:Record<string,string>}>('/hello{?q*}'),
async get(req, res) {
// `req` is inferred as BunRequest<{q:Record<string,string>}>
}
}
});
正如您所看到的,为了利用这个推断,您需要在声明它时使用routeMap
函数来包装您的对象文字,以便TypeScrip正确地推断它的类型.