reactjs - Typescript: React'te history nesnesi için tip kontrolü nasıl eklenir?


Aşağıdaki koda sahibim, bu kod bir history nesnesini prop olarak alıyor:

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>
);

Bu history özelliği için tür kontrolünü nasıl eklerim, bu özellik parent'ını withRouter HOC ile sarmalayarak alınmaktadır? Düşünebildiğim bir yol bunu şöyle yazmaktır:

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

Ama eminim ki bu doğru yol değil, çünkü history nesnesinin diğer özellikleri kayboluyor.

Bunu yapmanın doğru yolunu önerebilir misin?

@Oblosys'ın cevabına göre kod GÜNCELLENDİ

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));

Ama şimdi şu hatayı alıyorum:

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

Cevap #1

withRouter tarafından geçirilen tüm propsları bildiren RouteComponentProps arayüzünü kullanabilirsiniz:

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

RouteComponentProps için tip parametresi, match içindeki params özelliğinin tipidir, bu yüzden sadece adlandırılmış yol segmentlerini eşleştirmediğiniz sürece buna ihtiyacınız olmayacaktır.

Alternatif olarak, eğer history withRouter tarafından gelmiyorsa fakat kendisi bir prop olarak geçirilmişse, tipi history’den şu şekilde ithal edebilirsiniz:

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

Cevap #2

Bulduğum en basit çözüm

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

....

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

Cevap #3

Hook'larla React 16.8 için:

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

İlgili makaleler