如何在依赖于兄弟类型的复杂对象中强制类型



我正在寻找构建具有内部约束的选项类型我希望用户定义一些验证调用者的方法然后,在每条路由上,用户可以定义每个呼叫方是否可以访问这条路由(保护)。

我想防止用户为未定义的身份验证类型定义Guard并将认证方法返回的上下文作为参数

提供给守卫这里有一个例子

type Options = {
auths: {
[key: string]: (req) => ? | null;
}
routes: [
{
guard: {
[?]: boolean | ((ctxt: ?) => boolean);
}
}
]
}
const options: Options = {
auths: {
CUSTOMER: (req): Customer => {
if (!isCustomer()) {
throw new Error('Not a customer');
}
return { name: req.body.name };
},
COLLABORATOR: (req): Collaborator => {
if (!isCollaborator()) {
throw new Error('Not a collaborator');
}
return { ldap: req.body.ldap };
},
},
routes: [ {
guard: {
CUSTOMER: false,
COLLABORATOR: (collaborator: Collaborator) => isDevelopper(collaborator),
SERVICE: false, // Should trigger a type error
}
} ]
}

这个例子拒绝所有的客户和所有的合作者,除了开发人员

谢谢你的帮助

我找到了第一个解决方案

type Options<T extends Record<string,  unknown>> = {
auths: {
[Property in keyof T]: (req: Request) => T[Property];
};
routes: [
{
guard: {
[Property in keyof T]?: boolean | ((ctxt: T[Property]) => boolean);
}
}
]
}

有没有办法不强迫用户定义泛型类型?

type Context = {
CUSTOMER: Customer;
COLLABORATOR: Collaborator;
}

如果我理解正确,您会对所描述的解决方案感到满意,前提是有一种方法不必显式指定T(这里是Context)泛型类型?

泛型类型的自动推断只发生在函数/构造函数参数中。

因此,一个经典的解决方法是使用"transparent"函数,除了用于此自动推理之外没有其他功能:
// "Transparent" function, used only for automatic inference of generic type
function inferOptionsContext<T extends Record<string,  unknown>>(options: Options<T>) {
return options;
}
inferOptionsContext({
auths: { // Error: Property 'SERVICE' is missing in type '{ CUSTOMER: (req: Request) => Customer; COLLABORATOR: (req: Request) => Collaborator; }' but required in type '{ CUSTOMER: (req: Request) => unknown; COLLABORATOR: (req: Request) => Collaborator; SERVICE: (req: Request) => unknown; }'.
CUSTOMER: (req): Customer => {
if (!isCustomer()) {
throw new Error('Not a customer');
}
return { name: req.body?.name };
},
COLLABORATOR: (req): Collaborator => {
if (!isCollaborator()) {
throw new Error('Not a collaborator');
}
return { ldap: req.body?.ldap };
},
},
routes: [ {
guard: {
CUSTOMER: false,
COLLABORATOR: (collaborator: Collaborator) => isDevelopper(collaborator),
SERVICE: false, // Should trigger a type error // Actually the error is triggered on auths
}
} ]
});

操场上联系

最新更新