Kayo
Kayo

Reputation: 189

Why TypeScript does not infer the type of values and how to avoid this behavior

I implements type-safe router in TypeScript and have a trouble with inferring types.

export interface Route<Args> {
  match(path: string): Args | void;
  build(args: Args): string;
}

export type Routes<State> = {[Tag in keyof State]: Route<State[Tag]>};

export interface Router<State> {
  match(path: string): Partial<State> | void;
  build(state: Partial<State>): string;
}

export function createRouter<State>(routes: Routes<State>): Router<State> {
  /* ... */ return {} as any;
}

const root: Route<{}> = {
  match: (path) => /* ... */ undefined,
  build: () => '/'
};

const blog: Route<{ id: string }> = {
  match: (path) => /* ... */ undefined,
  build: ({ id }) => '/blog/' + id
};

const router1 = createRouter({ root, blog });
const router2 = createRouter<{ root: {}, blog: { id: string } }>({ root, blog });
const router3 = createRouter(<Routes<{ root: {}, blog: { id: string } }>>{ root, blog });

The inferred type of router1 is a Router<{root: any, blog: any}>. But I expected the router would have a type Router<{root:{}, blog:{id:string}}>.

I tried to add type parameter (see router2) and it works as expected.

Also I assumed that [email protected] cannot infer type of routes object and I added type explicitly (the router3). It also works right.

Are there any ways to solve this issue without adding types explicitly? At least I would like to get reasonable explanation why TS treat value types as any in this case.

Upvotes: 2

Views: 198

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 250056

This issue is fixed in Typescript 2.8. It might be related to this issue

Proof

Upvotes: 2

Related Questions