Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make typescript see props from decorators

I have simple component that uses mobx and decorators like this

import * as React from "react";
import { observer, inject } from "mobx-react/native";
import { Router as ReactRouter, Switch, Route } from "react-router-native";
import Dashboard from "./_dashboard";
import { RouterInterface } from "../store/_router";

// -- types ----------------------------------------------------------------- //
export interface Props {
  router: RouterInterface;
}

@inject("router")
@observer
class Router extends React.Component<Props, {}> {
  // -- render -------------------------------------------------------------- //
  render() {
    const { router } = this.props;
    return (
      <ReactRouter history={router.history}>
        <Switch location={router.location}>
          <Route path="/" component={Dashboard} />
        </Switch>
      </ReactRouter>
    );
  }
}

export default Router;

essentially @inject("router") adds this.props.router that satisfies Props interface above, however typescript doesn't account for this and whenever I use this component somewhere I get an error if I don't pass down router in props, hence I need to change to router?: RouterInterface; which is fine, but not ideal.

Is there a way to fix this issue where typescript accounts for decorators injecting the props?

like image 513
Ilja Avatar asked Nov 06 '17 14:11

Ilja


1 Answers

There is a way around it.
You can declare your injected props in a separate interface and then write a getter function. I wrote about it here:
https://gist.github.com/JulianG/18af9b9ff582764a87639d61d4587da1#a-slightly-better-solution

interface InjectedProps {
  bananaStore: BananaStore; // 👍 no question mark here
}

interface BananaProps {
  label: string;
}

class BananaComponent extends Component<BananaProps> {

  get injected(): InjectedProps {
    return this.props as BananaProps & InjectedProps;
  }

  render() {
    const bananas = this.injected.bananaStore.bananas; // 👍 no exclamation mark here
    return <p>{this.props.label}:{bananas}</p>
  }

}
like image 110
JulianG Avatar answered Oct 19 '22 15:10

JulianG