Skip to content

Commit

Permalink
Improve state and router param types.
Browse files Browse the repository at this point in the history
Co-authored-by: Zeng Xian <xian.zeng@iftech.io>
  • Loading branch information
kitsonk and themez committed May 26, 2020
1 parent 48b1a41 commit 5e591f9
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 83 deletions.
22 changes: 12 additions & 10 deletions application.ts
Expand Up @@ -90,10 +90,10 @@ export class ApplicationErrorEvent<S extends State> extends ErrorEvent {
* The `context.state` can be typed via passing a generic argument when
* constructing an instance of `Application`.
*/
export class Application<S extends State = Record<string, any>>
export class Application<AS extends State = Record<string, any>>
extends EventTarget {
#keys?: KeyStack;
#middleware: Middleware<S, Context<S>>[] = [];
#middleware: Middleware<State, Context<State>>[] = [];
#serve: typeof defaultServe;
#serveTls: typeof defaultServeTls;

Expand Down Expand Up @@ -125,9 +125,9 @@ export class Application<S extends State = Record<string, any>>
* const app = new Application({ state: { foo: "bar" } });
*
*/
state: S;
state: AS;

constructor(options: ApplicationOptions<S> = {}) {
constructor(options: ApplicationOptions<AS> = {}) {
super();
const {
state,
Expand All @@ -137,14 +137,14 @@ export class Application<S extends State = Record<string, any>>
} = options;

this.keys = keys;
this.state = state ?? {} as S;
this.state = state ?? {} as AS;
this.#serve = serve;
this.#serveTls = serveTls;
}

/** Deal with uncaught errors in either the middleware or sending the
* response. */
#handleError = (context: Context<S>, error: any): void => {
#handleError = (context: Context<AS>, error: any): void => {
if (!(error instanceof Error)) {
error = new Error(`non-error thrown: ${JSON.stringify(error)}`);
}
Expand Down Expand Up @@ -180,7 +180,7 @@ export class Application<S extends State = Record<string, any>>
handling: boolean;
closing: boolean;
closed: boolean;
middleware: (context: Context<S>) => Promise<void>;
middleware: (context: Context<AS>) => Promise<void>;
server: Server;
}) => {
const context = new Context(this, request);
Expand All @@ -207,7 +207,7 @@ export class Application<S extends State = Record<string, any>>

addEventListener(
type: "error",
listener: ApplicationErrorEventListenerOrEventListenerObject<S> | null,
listener: ApplicationErrorEventListenerOrEventListenerObject<AS> | null,
options?: boolean | AddEventListenerOptions,
): void;
addEventListener(
Expand Down Expand Up @@ -280,8 +280,10 @@ export class Application<S extends State = Record<string, any>>
}

/** Register middleware to be used with the application. */
use(...middleware: Middleware<S, Context<S>>[]): this {
use<S extends State = AS>(
...middleware: Middleware<S, Context<S>>[]
): Application<S extends AS ? S : (S & AS)> {
this.#middleware.push(...middleware);
return this;
return this as Application<any>;
}
}
15 changes: 15 additions & 0 deletions application_test.ts
Expand Up @@ -365,3 +365,18 @@ test({
}, TypeError);
},
});

test({
name: "app.state type handling",
fn() {
const app = new Application({ state: { id: 1 } });
app.use((ctx: Context<{ session: number }>) => {
ctx.state.session = 0;
}).use((ctx) => {
ctx.state.id = 1;
ctx.state.session = 2;
// @ts-expect-error
ctx.state.bar = 3;
});
},
});

0 comments on commit 5e591f9

Please sign in to comment.