Snabel
Snabel
DDeno
Created by Snabel on 2/11/2023 in #help
My magic middlewares type
If anyone wants a typescript challange here is one: I am trying to create a tuple type which contains an sequence of MiddlewareHandler types. This MiddlewareHandler is defined as:
export type MiddlewareHandler<I = unknown, O extends I = I> = (
req: Request,
ctx: MiddlewareContext<I, O>,
) => Response | Promise<Response>;
export type MiddlewareHandler<I = unknown, O extends I = I> = (
req: Request,
ctx: MiddlewareContext<I, O>,
) => Response | Promise<Response>;
I have a function called compose which composes these MiddlewareHandlers. This function takes a generic array of MiddlewareHandler:
type ExtractInput<T extends readonly MiddlewareHandler[]> = T[0] extends
MiddlewareHandler<infer I> ? I : never;
type ExtractOutput<T extends readonly MiddlewareHandler[]> =
T[T["length"]] extends MiddlewareHandler<infer _, infer O> ? O : never;

export function compose<T extends readonly MiddlewareHandler[]>(
middlewares: T,
handler: Handler<ExtractOutput<T>>,
): Handler<ExtractInput<T>> { ... }
type ExtractInput<T extends readonly MiddlewareHandler[]> = T[0] extends
MiddlewareHandler<infer I> ? I : never;
type ExtractOutput<T extends readonly MiddlewareHandler[]> =
T[T["length"]] extends MiddlewareHandler<infer _, infer O> ? O : never;

export function compose<T extends readonly MiddlewareHandler[]>(
middlewares: T,
handler: Handler<ExtractOutput<T>>,
): Handler<ExtractInput<T>> { ... }
this however does not work, as it complains when using it like following:
export const auth = {
"/logout": compose(
[session(), authenticated()] as const,
logout
),
"/github": github
} satisfies Routes;
export const auth = {
"/logout": compose(
[session(), authenticated()] as const,
logout
),
"/github": github
} satisfies Routes;
Argument of type 'readonly [MiddlewareHandler<unknown, SessionState>, MiddlewareHandler<SessionState, Required<SessionState>>]' is not assignable to parameter of type 'readonly MiddlewareHandler<unknown, unknown>[]'.
Type 'MiddlewareHandler<unknown, SessionState> | MiddlewareHandler<SessionState, Required<SessionState>>' is not assignable to type 'MiddlewareHandler<unknown, unknown>'.
Type 'MiddlewareHandler<SessionState, Required<SessionState>>' is not assignable to type 'MiddlewareHandler<unknown, unknown>'.
Types of parameters 'ctx' and 'ctx' are incompatible.
Type 'MiddlewareContext<unknown, unknown>' is not assignable to type 'MiddlewareContext<SessionState, Required<SessionState>>'.
Property 'session' is missing in type 'MiddlewareContext<unknown, unknown>' but required in type 'Required<SessionState>'.deno-ts(2345)
Argument of type 'readonly [MiddlewareHandler<unknown, SessionState>, MiddlewareHandler<SessionState, Required<SessionState>>]' is not assignable to parameter of type 'readonly MiddlewareHandler<unknown, unknown>[]'.
Type 'MiddlewareHandler<unknown, SessionState> | MiddlewareHandler<SessionState, Required<SessionState>>' is not assignable to type 'MiddlewareHandler<unknown, unknown>'.
Type 'MiddlewareHandler<SessionState, Required<SessionState>>' is not assignable to type 'MiddlewareHandler<unknown, unknown>'.
Types of parameters 'ctx' and 'ctx' are incompatible.
Type 'MiddlewareContext<unknown, unknown>' is not assignable to type 'MiddlewareContext<SessionState, Required<SessionState>>'.
Property 'session' is missing in type 'MiddlewareContext<unknown, unknown>' but required in type 'Required<SessionState>'.deno-ts(2345)
Plus points: I would ideally also like the T generic type to require that all following MiddlewareHandlers have the its generic I set to the previous O like following type:
[MiddlewareHandler<unknown, A>, MiddlewareHandler<A, B>, MiddlewareHandler<B, C>];
^>------------------->^ ^>------------------->^
[MiddlewareHandler<unknown, A>, MiddlewareHandler<A, B>, MiddlewareHandler<B, C>];
^>------------------->^ ^>------------------->^
1 replies
DDeno
Created by Snabel on 9/30/2022 in #help
Monkey patch Broadcast Channel to send messages to current context
Essentially what I want to do is be able to connect to new BroadcastChannel("test_channel"); which I in the same context want to post messages to and still be able to recieve them. So if my pretty little drawing helps:
|---same javascript context----------|
| |-patched test_channel source----| |
| | Send messages here! | |
| |--------------------------------| |
| |
| |-test_channel-------------------| |
| | Recieve messages here | |
| |--------------------------------| |
| |
| |-test_channel-------------------| |
| | and here! | |
| |--------------------------------| |
|------------------------------------|
|---same javascript context----------|
| |-patched test_channel source----| |
| | Send messages here! | |
| |--------------------------------| |
| |
| |-test_channel-------------------| |
| | Recieve messages here | |
| |--------------------------------| |
| |
| |-test_channel-------------------| |
| | and here! | |
| |--------------------------------| |
|------------------------------------|
6 replies