Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Default function value in React component using Typescript

The question is very similar to this, but mine is focused on the default function. (I'm new to front-end, please let me know if there's a more official name for it)

This is the code (I'm using TypeScript 2.5):

export const TestProps = {
    Hello: (name: string) => {
        console.log(name);
    }
}

type TestPropsType = typeof TestProps;

export class TestComp extends React.Component<TestPropsType, {}>{    
    public render() {
        this.props.Hello("world");
        return <div>test</div>;
    }
}

Then, when I try to render this component:

ReactDOM.render(<TestComp />, document.getElementById("page"));

I got this error;

TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes & Readonly<{ children?: ReactNode; }> & ...'. Type '{}' is not assignable to type 'Readonly<{ Hello: (name: string) => void; }>'.

Property 'Hello' is missing in type '{}'.

How can I fix this problem?

like image 310
Charlie Avatar asked Oct 28 '22 23:10

Charlie


1 Answers

First, let's fix your example:

interface TestProps {
    Hello?: { (name: string): void };
}

export class TestComp extends React.Component<TestProps, {}> {    
    public static defaultProps: Partial<TestProps> = {
        Hello: name => console.log(name)
    };

    public render() {
        this.props.Hello("world");
        return <div>test</div>;
    }
}

The way that you had it written before meant that your component couldn't see TestProps (it wasn't passed in from anywhere) and that Hello was a required prop. I used an interface with Hello? to make it optional, rather than using typeof.

The compiler error came from the fact that Hello was required, so you would have needed to use:

ReactDOM.render(<TestComp Hello={() => {}} />, document.getElementById("page"));
                       // ^ pass Hello as a prop here

Doing this would fix the compile error, but you would still be left with incorrect behaviour, as the object TestProps in your example would never be used.

If you are using strictNullChecks, then you will have to work your way around the type system a little bit, since Hello is an optional property:

if (this.props.Hello) this.props.Hello("world");
// or
this.props.Hello && this.props.Hello("world");

By checking whether this.props.Hello is truthy, the type is narrowed from (name: string) => void | undefined to just (name: string) => void, so you can call the function.

like image 70
Tom Fenech Avatar answered Nov 15 '22 06:11

Tom Fenech