정리
This commit is contained in:
@@ -1,25 +1,25 @@
|
|||||||
import { InvalidConversion } from "./base";
|
import { InvalidConversion } from "./base";
|
||||||
|
|
||||||
export interface Converter<Out, In extends object = Record<string, never>> {
|
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>;
|
type Empty = Record<string, never>;
|
||||||
|
|
||||||
interface Login {
|
type Login = {
|
||||||
userID: number;
|
userID: number;
|
||||||
}
|
}
|
||||||
interface GameLogin {
|
type GameLogin = {
|
||||||
userID: number;
|
userID: number;
|
||||||
generalID: number;
|
generalID: number;
|
||||||
}
|
}
|
||||||
interface UserLevel {
|
type UserLevel = {
|
||||||
userID: number;
|
userID: number;
|
||||||
userLevel: number;
|
userLevel: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ParseUserLevel<Q extends Login = Login>(): Converter<Q & UserLevel, Q> {
|
export function ParseUserLevel<Q extends Login = Login>(): Converter<Q & UserLevel, Q> {
|
||||||
return (inCtx: Q): Q & UserLevel => {
|
return (inCtx) => {
|
||||||
return {
|
return {
|
||||||
userLevel: 123,
|
userLevel: 123,
|
||||||
...inCtx,
|
...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> {
|
export function ReqLogin<Q extends object = Empty>(): Converter<Q & Login, Q> {
|
||||||
return (inCtx: Q): Q & Login => {
|
return (inCtx) => {
|
||||||
return {
|
return {
|
||||||
userID: 999,
|
userID: 999,
|
||||||
...inCtx,
|
...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> {
|
export function ReqGameLogin<Q extends Login = Login>(): Converter<Q & GameLogin, Q> {
|
||||||
return (inCtx: Q): Q & GameLogin => {
|
return (inCtx) => {
|
||||||
return {
|
return {
|
||||||
generalID: inCtx.userID * 4,
|
generalID: inCtx.userID * 4,
|
||||||
...inCtx,
|
...inCtx,
|
||||||
@@ -45,28 +45,70 @@ export function ReqGameLogin<Q extends Login = Login>(): Converter<Q & GameLogin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const x = [
|
type Compose2<B, A extends object, D, C> = D & B extends A & C ? B extends C ? Converter<D & B, A> : never : never;
|
||||||
ReqLogin(),
|
export type Chain<T> =
|
||||||
ParseUserLevel(),
|
T extends readonly [() => Converter<infer B, infer A>] ? Converter<B, A> :
|
||||||
] 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> :
|
|
||||||
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>] ? 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]> :
|
T extends readonly [() => Converter<infer B, infer A>, () => Converter<infer D, infer C>, ... infer R] ? Chain<[() => Compose2<B, A, D, C>, ...R]> :
|
||||||
never;
|
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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user