Videos
import React from "react";
interface FooterProps {
/* list of props */
}
export const Footer: React.FC<FooterProps> = ({}) => {
return <div>Footer</div>;
};
export const Footer2 = (props: FooterProps) => {
return <div>Footer</div>;
};Which one of them is a better way to define a component with props? And what exactly is the difference?
2019: noticed all answers above are quite outdated so here is a fresh one.
Lookup type
With newer TS versions you can use lookup types.
type ViewProps = View['props']
Despite being very convenient, that will only work with class components.
React.ComponentProps
The React typedefs ship with an utility to extract the type of the props from any component.
type ViewProps = React.ComponentProps<typeof View>
type InputProps = React.ComponentProps<'input'>
This is a bit more verbose, but unlike the type lookup solution:
- the developer intent is more clear
- this will work with BOTH functional components and class components
All this makes this solution the most future-proof one: if you decide to migrate from classes to hooks, you won't need to refactor any client code.
Starting with TypeScript 2.8, you can use conditional types, e.g. given:
interface MyComponentProps { bar: string; }
declare const MyComponent: React.Component<MyComponentProps>;
interface MyComponentClassProps { bar: string; }
declare const MyComponentClass: React.ComponentClass<MyComponentClassProps>;
interface MyStatelessComponentProps { bar: string; }
declare const MyStatelessComponent: React.StatelessComponent<MyStatelessComponentProps>;
We can define these helpers:
type GetComponentProps<T> = T extends React.ComponentType<infer P> | React.Component<infer P> ? P : never
And use them like so:
// $ExpectType MyComponentProps
type MyComponentPropsExtracted = GetComponentProps<typeof MyComponent>
// $ExpectType MyComponentClassProps
type MyComponentClassPropsExtracted = GetComponentProps<typeof MyComponentClass>
// $ExpectType MyStatelessComponentProps
type MyStatelessComponentPropsExtracted = GetComponentProps<typeof MyStatelessComponent>
Update 2018-12-31: this is now available in the official React typings via React.ComponentProps.
I think you have a couple small issues in DisplayPerson.tsx. I've fixed them in this codesandbox: https://codesandbox.io/s/modest-snyder-s5bmt?file=/src/App.tsx
DisplayPerson.tsx:
import React from 'react';
import { Person } from '../App';
export default function DisplayPerson({ person }: { person: Person }) {
return (
<div>
<h1>{person.firstName}</h1>
<h1>{person.lastName}</h1>
</div>
);
}
- Your prop type is incorrect. Instead of
{ person }: Personyou should have{ person }: { person: Person }. - You should wrap
person.firstNameandperson.lastNamewith{}
To elaborate on #1: The props passed into DisplayPerson is an object where the key is the prop name and the value is whatever's passed in. Therefore, the type of the props object isn't Person but rather an object with key person and a value of type Person.
You need to correct your props part. So your DisplayPerson.tsx file will be like this
import React from 'react';
import { Person } from '../App';
interface IProps {
person: Person
}
export default function DisplayPerson({ person }: IProps) {
return (
<div>
<h1>{person.firstName}</h1>
<h1>{person.lastName}</h1>
</div>
);
}
Update:
In React, the structure is like below for Functional component
function DisplayPerson(props) {}
as you see here props is a parameter that is of type object. so you need to pass an object. Now you want a person as a key inside that object which is Object deconstruction.
That's why it has to be done like #1 from the answer of Nathan.
You can refer this: https://javascript.info/destructuring-assignment#object-destructuring