This commit is contained in:
2023-08-07 18:48:26 +00:00
parent b30dde442b
commit 507cba34eb
+68 -26
View File
@@ -1,25 +1,25 @@
import { InvalidConversion } from "./base";
export interface Converter<Out, In extends object = Record<string, never>> {
(inCtx: In): Out;
(inCtx: In, req: Request, res: Response): Out | InvalidConversion;
}
type Empty = Record<string, never>;
interface Login {
type Login = {
userID: number;
}
interface GameLogin {
type GameLogin = {
userID: number;
generalID: number;
}
interface UserLevel {
type UserLevel = {
userID: number;
userLevel: number;
}
export function ParseUserLevel<Q extends Login = Login>(): Converter<Q & UserLevel, Q> {
return (inCtx: Q): Q & UserLevel => {
return (inCtx) => {
return {
userLevel: 123,
...inCtx,
@@ -28,7 +28,7 @@ export function ParseUserLevel<Q extends Login = Login>(): Converter<Q & UserLev
}
export function ReqLogin<Q extends object = Empty>(): Converter<Q & Login, Q> {
return (inCtx: Q): Q & Login => {
return (inCtx) => {
return {
userID: 999,
...inCtx,
@@ -37,7 +37,7 @@ export function ReqLogin<Q extends object = Empty>(): Converter<Q & Login, Q> {
}
export function ReqGameLogin<Q extends Login = Login>(): Converter<Q & GameLogin, Q> {
return (inCtx: Q): Q & GameLogin => {
return (inCtx) => {
return {
generalID: inCtx.userID * 4,
...inCtx,
@@ -45,28 +45,70 @@ export function ReqGameLogin<Q extends Login = Login>(): Converter<Q & GameLogin
}
}
const x = [
ReqLogin(),
ParseUserLevel(),
] as const;
const y = [
ReqLogin,
ParseUserLevel,
ReqGameLogin,
] as const;
type Split<A> = A extends (q: infer Q) => infer R ? [Q, R] : never;
type Compose<B, A> = B extends A ? B : never;
type Compose2<B, A extends object, D, C extends object> = D & B extends A & C ? B extends C ? Converter<D, A> : never : never;
type Chain<T> =
T extends readonly [() => Converter<infer B, infer A>] ? Converter<B & A, A> :
type Compose2<B, A extends object, D, C> = D & B extends A & C ? B extends C ? Converter<D & B, A> : never : never;
export type Chain<T> =
T extends readonly [() => Converter<infer B, infer A>] ? Converter<B, A> :
T extends readonly [() => Converter<infer B, infer A>, () => Converter<infer D, infer C>] ? Compose2<B, A, D, C> :
T extends readonly [() => Converter<infer B, infer A>, () => Converter<infer D, infer C>, ... infer R] ? Chain<[() => Compose2<B, A, D, C>, ...R]> :
never;
type Solve<T> = T extends Converter<infer B, infer A> ? Empty extends A ? B : never : never;
export type Solve<T> = T extends Converter<infer B, infer A> ? Empty extends A ? B : never : never;
type Z = Solve<Chain<typeof y>>;
const q1 = [
ReqLogin,
ParseUserLevel,
ReqGameLogin,
] as const;
const q2 = [
ReqLogin,
] as const;
type R1 = Solve<Chain<typeof q1>>;
type R2 = Solve<Chain<typeof q2>>;
const r1: R1 = undefined as unknown as R1;
const r2: R2 = undefined as unknown as R2;
r1.userLevel;
r2.userID;
function test(req: Request, res: Response){
const a0 = ReqLogin()({}, req, res);
if('isInvalid' in a0){
return false;
}
const a1 = ParseUserLevel()(a0, req, res);
if('isInvalid' in a1){
return false;
}
const a2 = ReqGameLogin()(a1, req, res);
if('isInvalid' in a2){
return false;
}
return true;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type Converters = readonly (() => Converter<any, any>)[];
function test2<T extends Converters>(req: Request, res: Response, chain: T): Solve<Chain<T>> | false{
const actors = chain.map((v) => v());
let result = {};
for(const actor of actors){
result = actor(result, req, res);
if('isInvalid' in result){
return false;
}
}
return result as Solve<Chain<T>>;
}
const finalResult1 = test2({} as Request, {} as Response, q1);
if(finalResult1 !== false){
finalResult1.userLevel;
}