Skip to content

Commit a6155cd

Browse files
committed
add conditional rendering
cc typescript-cheatsheets/react#12 (comment)
1 parent bf8edc1 commit a6155cd

File tree

1 file changed

+37
-7
lines changed

1 file changed

+37
-7
lines changed

README.md

+37-7
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ Translations: [中文翻译](https://github.com/fi3ework/blog/tree/master/react-
4242
* [Enum Types](#enum-types)
4343
* [Type Assertion](#type-assertion)
4444
* [Intersection Types](#intersection-types)
45+
* [Types for Conditional Rendering](#types-for-conditional-rendering)
4546
* [Omit attribute from a type](#omit-attribute-from-a-type)
4647
* [Type Zoo](#type-zoo)
4748
- [Troubleshooting Handbook: TSLint](#troubleshooting-handbook-tslint)
@@ -860,6 +861,42 @@ export const PrimaryButton = (
860861
);
861862
```
862863

864+
## Types for Conditional Rendering
865+
866+
Components can render different things based on props that are passed in, and this can be confusing to type. Here is an example solution, see the further discussion for other solutions. *thanks to [@jpavon](https://github.com/sw-yx/react-typescript-cheatsheet/issues/12#issuecomment-394440577)*
867+
868+
<details>
869+
870+
```tsx
871+
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
872+
873+
interface LinkProps {}
874+
875+
type AnchorProps = React.AnchorHTMLAttributes<HTMLAnchorElement>
876+
type RouterLinkProps = Omit<NavLinkProps, 'href'>
877+
878+
const Link = <T extends {}>(
879+
props: LinkProps & T extends RouterLinkProps ? RouterLinkProps : AnchorProps
880+
) => {
881+
if ((props as RouterLinkProps).to) {
882+
return <NavLink {...props as RouterLinkProps} />
883+
} else {
884+
return <a {...props as AnchorProps} />
885+
}
886+
}
887+
888+
<Link<RouterLinkProps> to="/">My link</Link> // ok
889+
<Link<AnchorProps> href="/">My link</Link> // ok
890+
<Link<RouterLinkProps> to="/" href="/">My link</Link> // error
891+
```
892+
893+
<summary>Further Discussion</summary>
894+
895+
We have more discussion and examples [in our issue here](https://github.com/sw-yx/react-typescript-cheatsheet/issues/12).
896+
897+
</details>
898+
899+
863900
## Omit attribute from a type
864901

865902
Sometimes when intersecting types, we want to define our own version of an attribute. For example, I want my component to have a `label`, but the type I am intersecting with also has a `label` attribute. Here's how to extract that out:
@@ -894,13 +931,6 @@ export const Checkbox = (
894931
};
895932
```
896933

897-
<details>
898-
899-
<summary>Explanation</summary>
900-
901-
This is not yet written. Please PR or [File an issue](https://github.com/sw-yx/react-typescript-cheatsheet/issues/new) with your suggestions!
902-
</details>
903-
904934
## Type Zoo
905935

906936
As you can see from the Omit example above, you can write significant logic in your types as well. [type-zoo](https://github.com/pelotom/type-zoo) is a nice toolkit of operators you may wish to check out (includes Omit), as well as [utility-types](https://github.com/piotrwitek/utility-types) (especially for those migrating from Flow).

0 commit comments

Comments
 (0)