These snippet are used in the following articles:
Last active
January 7, 2023 04:06
-
-
Save jomifepe/98e4622e060113e9580af4bdd2dd53c0 to your computer and use it in GitHub Desktop.
Article Snippet - Clean up your React component types 🧼
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// types/util.ts | |
export type WithChildren<P = {}> = P & { children?: ReactNode }; | |
// components/MyComponent.tsx | |
import { WithChildren } from 'types/util.ts'; | |
const MyComponent1 = ({ children }: WithChildren) => <>{children}</>; | |
const MyComponent2 = ({ children }: WithChildren<MyProps>) => <>{children}</>; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type MyProps = { | |
children?: React.ReactNode; | |
/* … my properties */ | |
} | |
const MyComponent = ({ children }: MyProps) => <>{children}</>; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Letting TypeScript inferring the type: (props: MyProps) => JSX.Element 🚀 | |
const MyComponent = (props: MyProps) => <div>beep</div>; | |
// Explicitly defining a return type (3 similar options of writting the same as above) | |
const MyComponent = (props: MyProps): ReactElement => <div>boop</div>; | |
const MyComponent = (props: MyProps): JSX.Element => <div>boop</div>; | |
const MyComponent: FC<MyProps> = (props) => <div>boop</div>; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const List = (props: ListProps) => { /* JSX */ } | |
List.Item = (props: ItemProps) => { /* JSX */ } | |
// <List><List.Item></List> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const MyComponent = (props: MyProps) => { /* JSX */ } | |
MyComponent.displayName = 'MySpecialComponent'; | |
// Inferred type: | |
// const MyComponent: { | |
// (props: MyProps): JSX.Element; | |
// displayName: string; | |
// } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @types/react v16.9.35 | |
// FC is an alias for FunctionComponent | |
type FC<P = {}> = FunctionComponent<P>; | |
interface FunctionComponent<P = {}> { | |
(props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null; | |
propTypes?: WeakValidationMap<P>; | |
contextTypes?: ValidationMap<any>; | |
defaultProps?: Partial<P>; | |
displayName?: string; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type MyProps<T> = { | |
data: T; | |
onClick?: (item: T) => void; | |
} | |
// with a function declaration ✅ | |
function MyComponent<T>(props: MyProps<T>) { /* JSX */ } | |
// with a function expression ✅ | |
const MyComponent = <T>(props: MyProps<T>) => { /* JSX */ } | |
// We can pass anything to the data prop and it will infer the type |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const MyComponent = ({ name = 'John' }: MyProp) => <div>{name}</div> | |
// if the name is undefined, uses 'John' as a fallback |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type MyType = PropsWithChildren<{ name: string }> | |
// result: { name: string; children?: ReactNode } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const MyComponent = ({ children }: PropsWithChildren<MyProps>) => ( | |
<>{children}</> | |
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type ListComponentType = FC<ListProps> & { Item: FC<ItemProps> }; | |
const List: ListComponentType = (props) => { /* JSX */ } | |
List.Item = (props) => { /* JSX */ } | |
// <List><List.Item></List> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// These function expressions work fine ✅ | |
const MyComponent: FC<MyProps> = (props) => { /* JSX */ }; | |
const MyComponent: FC<MyProps> = function(props) { /* JSX */ } | |
const MyComponent = ((props) => { /* JSX */ }) as FC<MyProps> | |
// But function declarations don't ❌ | |
// The following options have invalid syntax: | |
function MyComponent: FC<MyProps> (props) { /* JSX */ } | |
function <FC<MyProps>>MyComponent(props) { /* JSX */ } | |
function MyComponent(props) { /* JSX */ } as FC<MyProps> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This won't work ❌ | |
const MyComponent: FC</* ??? */> = <T>(props: MyProps<T>) => { /* JSX */ } | |
// This syntax is not valid ❌ | |
const MyComponent: FC<MyProps<T>> = (props: MyProps<T>) => { /* JSX */ } | |
// Yay, the following code works ✅ | |
// But we lost type inference ❌ Is it even worth it? 🤷🏻♂️ | |
type MyComponentType<T = unknown> = FC<MyProps<T>> | |
const MyComponent: MyComponentType = (props) => { /* JSX */ } | |
const MyTypedComponent = MyComponent as MyComponentType<string[]>; | |
// Usage: | |
// <MyTypedComponent data={['beep', 'boop']} /> // ✅ | |
// <MyTypedComponent data={[123, 456]} /> // ❌ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment