80 votes

Typescript : Comment ajouter la vérification du type pour l'objet historique dans React ?

J'ai le morceau de code suivant, qui reçoit un objet historique comme prop :

const ChildComponent = ({ history }) => (
        <div className={styles.body}>
            <div className={styles.cta}>
                <FloatingActionButton onClick={() => history.push(routes[4].path)}>
                    <span>Click me</span>
                </FloatingActionButton>
            </div>
        </div>
);

Comment ajouter un contrôle de type pour cette proposition d'histoire, qui est reçu en enveloppant son parent avec withRouter HOC ? Un moyen auquel je pense est d'écrire quelque chose comme ceci :

interface Props {
    history: {
        push(url: string): void;
    };
}

Mais je suis sûr que ce n'est pas la bonne méthode, car le reste des propriétés de l'objet historique est perdu.

Pouvez-vous me suggérer la bonne façon de procéder ?

MISE À JOUR du code basé sur la réponse de @Oblosys

import { withRouter, RouteComponentProps } from "react-router-dom";

interface Props extends RouteComponentProps<any> {
   /* Parent component's props*/
}

class Parent extends React.Component<Props, {}> {
    render() {
        return <ChildComponent history={this.props.history} />;
    }
}

//Child component related stuff
interface ChildComponentProps extends RouteComponentProps<any> {}

const ChildComponent: React.SFC<ChildComponentProps> = (props) => (
  <div className={styles.body}>
     <div className={styles.cta}>
         <FloatingActionButton onClick={() => history.push(routes[4].path)}>
            <span>Click me</span>
         </FloatingActionButton>
     </div>
   </div>
);

function mapStateToProps(state: types.AppState) {
    /* related code */
}

function mapDispatchToProps(dispatch: Redux.Dispatch<types.AppState>{
    /* related code */
}

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Parent));

Mais, maintenant, j'obtiens l'erreur suivante :

Type '{ history: History; }' is not assignable to type 'ChildComponentProps'.
    Property 'match' is missing in type '{ history: History; }'

131voto

Oblosys Points 5035

Vous pouvez utiliser le RouteComponentProps qui déclare tous les props passés par l'interface withRouter :

import { RouteComponentProps } from 'react-router-dom';
..
interface ChildComponentProps extends RouteComponentProps<any> {
  /* other props for ChildComponent */
}
const ChildComponent : React.SFC<ChildComponentProps> = ({ history }) => (
  ..
);

Le paramètre de type à RouteComponentProps est le type de la params la propriété dans match Vous n'en aurez donc pas besoin, sauf si vous faites correspondre des segments de chemin nommés.

Par ailleurs, si history ne vient pas de withRouter mais est passé par lui-même en tant que prop, vous pouvez importer le type à partir de history :

import { History } from 'history';
..
interface ChildComponentProps {
  history : History
  /* other props for ChildComponent */
}
const ChildComponent : React.SFC<ChildComponentProps> = ({ history }) => (
  ..
);

0 votes

Maintenant, j'obtiens l'erreur suivante : Le type '{ history : History ; }' n'est pas assignable au type 'ChildComponentProps'. La propriété 'match' est manquante dans le type '{ history : Histoire ; }".

2 votes

Si vous enveloppez ChildComponent en withRouter vous n'aurez pas besoin de passer explicitement l'option history .

1 votes

J'ai ajouté une solution alternative dans le cas où vous voulez passer seulement history .

18voto

Siddharth Points 784

La solution la plus simple que j'ai trouvée

import { RouteComponentProps } from 'react-router-dom';

....

interface Foo{
  history: RouteComponentProps["history"];
  location: RouteComponentProps['location'];
  match: RouteComponentProps['match'];
}

4 votes

Cela n'a pas fonctionné pour moi avec TS > 4.0. J'ai dû faire RouteComponentProps["history"] . C'est un conseil très utile, mais si vous pouviez ajuster la réponse, ce serait génial !

10voto

Pour React 16.8 avec crochets :

...
import {withRouter, RouteComponentProps} from 'react-router-dom';
...
const ChildComponent: React.FunctionComponent<RouteComponentProps> = ({history}) => {
...
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X