2
votes

Im using Typescript in my React app. I want to strictly check the type of props being passed to my components and throw error if it doesnt match.

import React from "react";
import styles from "./ServiceDetailCard.css";

type Service = {
    amount: string;
    comments: string;
};

interface IProps {
    service: Service;
    myFunc: (count: number) => void; // The function passed from parent has different return type(boolean) and defaul param as string type. But typescript doesnt throw error. 
}

class ServiceDetailCard extends React.Component<IProps, any> {

    render() {
        console.log(typeof this.props.service.amount); // This prints number. Typscirpt should have thrown an error since interface specified is string. But it doesnt.
        return (
            <div className={styles.serviceDetailCard}>
                <div className={styles.amount}>
                    <span className={styles.figure}>{this.props.service.amount}</span>
                </div>
            </div>
        );
    }
}

export default ServiceDetailCard;

import React from "react";
import styles from "./ServiceDetails.css";
import ServiceDetailsCard from "./ServiceDetailCard";

class ServiceDetails extends React.Component {
    render() {
        return (
            <div className={styles["service-details"]}>
                {this.props.data.map((service, index) => {
                    service.amount = 10; // To test, manually setting amount as number so that Typescript should throw error. But it doesnt.
                    return <ServiceDetailsCard key={index} service={service} myFunc={test} />;
                })}
            </div>
        );
    }
}

function test(number = 10) { // To test, manually setting the default param as string so that Typescript should throw error. But it doesnt.
    return true; // To test, manually setting return as boolean so that Typescript should throw error. But it doesnt.
}

export default ServiceDetails;

The service prop is expected to contain amount as number (specified via Interface) but even if I pass string from the parent component, it works and typescript doesnt throw error.

Same for the function prop myFunc which expects number params and return type is void. But Im passing different type default param and the return type is boolean.

Why doesnt typescript throw error?

This is my .tsconfig:

{
    "compilerOptions": {
        "outDir": "./www/",
        "sourceMap": true,
        "noImplicitAny": true,
        "strict": true,
        "strictNullChecks": true,
        "module": "es6", // specify module code generation
        "moduleResolution": "node",
        "jsx": "react", // use typescript to transpile jsx to js
        "target": "es5", // specify ECMAScript target version
        "allowJs": true, // allow a partial TypeScript and JavaScript codebase
        "allowSyntheticDefaultImports": true
    },
    "include": ["./src/**/*"]
}

Please advise.

1
It's correct. Your service prop expects amount as string, not number.paibamboo
And I think you should get error Property data does not exist, do you?paibamboo
@paibamboo No, Im not getting any error at all. Service.amount accepts number without throwing any error.Ivin Jose

1 Answers

3
votes

Your ServiceDetails do not specify props type, so value of this.props.data is any. TypeScript do not infer type from setting value to any.

let services: any;
services.ammount = 42;
// services is still any, and services.ammount also is any.

To fix the problem declare ServiceDetails props explicit.

 interface Service {
     ammount: number;
 }

interface ServiceDetailsProps {
    services: Service[];
}

class ServiceDetails extends React.Component<ServiceDetailsProps, {}> {
...