정리
This commit is contained in:
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user