Skip to content

Commit

Permalink
Make router type-safe
Browse files Browse the repository at this point in the history
  • Loading branch information
piscisaureus committed May 20, 2018
1 parent 1e67a10 commit 7332616
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 11 deletions.
35 changes: 26 additions & 9 deletions src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
limitations under the License.
*/

import { Component, h } from "preact";
import { Component, ComponentConstructor, h } from "preact";
import * as db from "./db";
import { push, Router } from "./router";
import * as types from "./types";
Expand All @@ -27,15 +27,32 @@ import { Notebook } from "./components/notebook";
import { Profile } from "./components/profile";
import { Recent } from "./components/recent";

interface BindProps {
[key: string]: (props: any) => Promise<any>;
type Partial<T> = { [K in keyof T]?: T[K] };

type ReadOnly<T> = { readonly [K in keyof T]: T[K] };

interface PageProps {
path: string;
matches?: { [key: string]: string };
onReady?: () => void;
}

interface BindState {
data: { [key: string]: string };
type BindProps<P> = {
[K in keyof P]?: (props: ReadOnly<Partial<P> & PageProps>) => Promise<P[K]>
};

interface BindStateNormal<S> {
data: { [K in keyof S]: S[K] };
error: null;
}

interface BindStateError {
data: null;
error: string;
}

type BindState<S> = BindStateNormal<S> | BindStateError;

/**
* This react HOC can be used to bind result of some async
* methods to props of the given component (C).
Expand All @@ -48,8 +65,8 @@ interface BindState {
* }
* });
*/
function bind(C, bindProps: BindProps) {
return class extends Component<any, BindState> {
function bind<P>(C: ComponentConstructor<P, {}>, bindProps: BindProps<P>) {
return class extends Component<Partial<P> & PageProps, BindState<P>> {
state = { data: null, error: null };
prevMatches = null;
componentRef;
Expand All @@ -61,7 +78,7 @@ function bind(C, bindProps: BindProps) {
async loadData() {
if (equal(this.props.matches, this.prevMatches)) return;
this.prevMatches = this.props.matches;
const data = {};
const data: Partial<P> = {};
for (const key in bindProps) {
if (!bindProps[key]) continue;
try {
Expand All @@ -71,7 +88,7 @@ function bind(C, bindProps: BindProps) {
return;
}
}
this.setState({ data, error: null });
this.setState({ data: data as P, error: null });
}

render() {
Expand Down
4 changes: 2 additions & 2 deletions src/nb_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ function resetPage() {
function renderProfile(profileUid: string) {
const promise = createResolvable();
resetPage();
const el = h(ProfilePage, {
const el = h(ProfilePage as any, {
matches: {
userId: profileUid
},
Expand All @@ -199,7 +199,7 @@ async function renderAnonNotebook(): Promise<Notebook> {
const promise = createResolvable();
resetPage();
let notebookRoot;
const el = h(NotebookPage, {
const el = h(NotebookPage as any, {
matches: {
nbId: "default"
},
Expand Down

0 comments on commit 7332616

Please sign in to comment.