Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .github/ISSUE_TEMPLATE/advanced-cheatsheet.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
---
name: Advanced Cheatsheet
about: Report Issue/Suggest an idea for Advanced Cheatsheet
title: "[Advanced] ISSUE_TITLE_HERE"
title: '[Advanced] ISSUE_TITLE_HERE'
labels: ADVANCED
assignees: ''

---

**What cheatsheet is this about? (if applicable)**
Expand All @@ -13,4 +12,4 @@ Advanced cheatsheet

**What's your issue or idea?**

*Write here*
_Write here_
5 changes: 2 additions & 3 deletions .github/ISSUE_TEMPLATE/basic-cheatsheet.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
---
name: Basic Cheatsheet
about: Report Issue/Suggest an idea for Basic Cheatsheet
title: "[Basic] ISSUE_TITLE_HERE"
title: '[Basic] ISSUE_TITLE_HERE'
labels: BASIC
assignees: sw-yx

---

**What cheatsheet is this about? (if applicable)**
Expand All @@ -13,4 +12,4 @@ Basic cheatsheet

**What's your issue or idea?**

*Write here*
_Write here_
5 changes: 1 addition & 4 deletions .github/ISSUE_TEMPLATE/general-react-ts-question.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
---
name: General React+TS Question
about: Questions are welcome! We want to know and solve your pain points.
title: "[Question] QUESTION_TITLE_HERE"
title: '[Question] QUESTION_TITLE_HERE'
labels: good first issue
assignees: sw-yx

---


5 changes: 2 additions & 3 deletions .github/ISSUE_TEMPLATE/hoc-cheatsheet.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
---
name: HOC Cheatsheet
about: Report Issue/Suggest an idea for HOC Cheatsheet
title: "[HOC] ISSUE_TITLE_HERE"
title: '[HOC] ISSUE_TITLE_HERE'
labels: HOC
assignees: ''

---

**What cheatsheet is this about? (if applicable)**
Expand All @@ -13,4 +12,4 @@ HOC cheatsheet

**What's your issue or idea?**

*Write here*
_Write here_
5 changes: 2 additions & 3 deletions .github/ISSUE_TEMPLATE/migrating-cheatsheet.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
---
name: Migrating Cheatsheet
about: Report Issue/Suggest an idea for Migrating Cheatsheet
title: "[Migrating] ISSUE_TITLE_HERE"
title: '[Migrating] ISSUE_TITLE_HERE'
labels: MIGRATING
assignees: ''

---

**What cheatsheet is this about? (if applicable)**
Expand All @@ -13,4 +12,4 @@ Migrating cheatsheet

**What's your issue or idea?**

*Write here*
_Write here_
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
31 changes: 14 additions & 17 deletions ADVANCED.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,11 +378,11 @@ You want to allow `expanded` to be passed only if `truncate` is also passed, bec
You can do this by function overloads:

```tsx
import React from "react";
import React from 'react';

type CommonProps = {
children: React.ReactNode;
as: "p" | "span" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
as: 'p' | 'span' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
};

type NoTruncateProps = CommonProps & {
Expand All @@ -403,18 +403,13 @@ const isTruncateProps = (
function Text(props: NoTruncateProps): JSX.Element;
function Text(props: TruncateProps): JSX.Element;
function Text(props: NoTruncateProps | TruncateProps) {

if (isTruncateProps(props)) {
const { children, as: Tag, truncate, expanded, ...otherProps } = props;

const classNames = truncate ? ".truncate" : "";
const classNames = truncate ? '.truncate' : '';

return (
<Tag
className={classNames}
aria-expanded={!!expanded}
{...otherProps}
>
<Tag className={classNames} aria-expanded={!!expanded} {...otherProps}>
{children}
</Tag>
);
Expand All @@ -427,17 +422,20 @@ function Text(props: NoTruncateProps | TruncateProps) {

Text.defaultProps = {
as: 'span'
}
};
```

Using the Text component:

```tsx
const App: React.FC = () => (
<>
<Text>not truncated</Text> {/* works */}
<Text truncate>truncated</Text> {/* works */}
<Text truncate expanded>truncate-able but expanded</Text> {/* works */}

<Text truncate expanded>
truncate-able but expanded
</Text>
{/* works */}
{/* TS error: Property 'truncate' is missing in type '{ children: string; expanded: true; }' but required in type 'Pick<TruncateProps, "expanded" | "children" | "truncate">'} */}
<Text expanded>truncate-able but expanded</Text>
</>
Expand Down Expand Up @@ -676,7 +674,7 @@ export function useLoading() {
setState(true);
return aPromise.finally(() => setState(false));
};
return [isLoading, load] as const // infers [boolean, typeof load] instead of (boolean | typeof load)[]
return [isLoading, load] as const; // infers [boolean, typeof load] instead of (boolean | typeof load)[]
}
```

Expand Down Expand Up @@ -852,7 +850,6 @@ This is taken from [the `tsdx` PR](https://github.com/palmerhq/tsdx/pull/70/file
More `.eslintrc.json` options to consider with more options you may want for **apps**:

```json

{
"extends": [
"airbnb",
Expand Down Expand Up @@ -893,7 +890,7 @@ More `.eslintrc.json` options to consider with more options you may want for **a
}
```

You can read a [fuller TypeScript + ESLint setup guide here](https://github.com/MatterhornDev/matterhorn-posts/blob/learn-typescript-linting/learn-typescript-linting.md) from Matterhorn, in particular check https://github.com/MatterhornDev/learn-typescript-linting.
You can read a [fuller TypeScript + ESLint setup guide here](https://github.com/MatterhornDev/matterhorn-posts/blob/learn-typescript-linting/learn-typescript-linting.md) from Matterhorn, in particular check https://github.com/MatterhornDev/learn-typescript-linting.

## Working with Non-TypeScript Libraries (writing your own index.d.ts)

Expand All @@ -910,8 +907,8 @@ So create a `.d.ts` file anywhere in your project with the module definition:
```ts
// de-indent.d.ts
declare module 'de-indent' {
function deindent(): void
export = deindent // default export
function deindent(): void;
export = deindent; // default export
}
```

Expand Down
4 changes: 2 additions & 2 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@

## Contributors

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore -->
<table><tr><td align="center"><a href="https://github.com/ferdaber"><img src="https://avatars2.githubusercontent.com/u/12239873?v=4" width="100px;" alt="Ferdy Budhidharma"/><br /><sub><b>Ferdy Budhidharma</b></sub></a><br /><a href="#review-ferdaber" title="Reviewed Pull Requests">👀</a> <a href="#maintenance-ferdaber" title="Maintenance">🚧</a> <a href="#content-ferdaber" title="Content">🖋</a></td><td align="center"><a href="https://twitter.com/swyx"><img src="https://avatars1.githubusercontent.com/u/6764957?v=4" width="100px;" alt="swyx"/><br /><sub><b>swyx</b></sub></a><br /><a href="#ideas-sw-yx" title="Ideas, Planning, & Feedback">🤔</a> <a href="#review-sw-yx" title="Reviewed Pull Requests">👀</a> <a href="#maintenance-sw-yx" title="Maintenance">🚧</a> <a href="#content-sw-yx" title="Content">🖋</a> <a href="#question-sw-yx" title="Answering Questions">💬</a></td><td align="center"><a href="https://github.com/eps1lon"><img src="https://avatars3.githubusercontent.com/u/12292047?v=4" width="100px;" alt="Sebastian Silbermann"/><br /><sub><b>Sebastian Silbermann</b></sub></a><br /><a href="#review-eps1lon" title="Reviewed Pull Requests">👀</a> <a href="#maintenance-eps1lon" title="Maintenance">🚧</a> <a href="#content-eps1lon" title="Content">🖋</a></td><td align="center"><a href="https://www.linkedin.com/in/islam-attrash-46703a94/"><img src="https://avatars0.githubusercontent.com/u/7091543?v=4" width="100px;" alt="Islam Attrash"/><br /><sub><b>Islam Attrash</b></sub></a><br /><a href="#maintenance-Attrash-Islam" title="Maintenance">🚧</a> <a href="#content-Attrash-Islam" title="Content">🖋</a></td><td align="center"><a href="https://stephenkoo.github.io/"><img src="https://avatars2.githubusercontent.com/u/18624246?v=4" width="100px;" alt="Stephen Koo"/><br /><sub><b>Stephen Koo</b></sub></a><br /><a href="#question-stephenkoo" title="Answering Questions">💬</a> <a href="#example-stephenkoo" title="Examples">💡</a></td></tr></table>

<!-- ALL-CONTRIBUTORS-LIST:END -->

Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore -->
<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
50 changes: 28 additions & 22 deletions HOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,33 +356,38 @@ function Dog({name, owner}: DogProps) {
And we have a `withOwner` HOC that injects the `owner`:

```tsx
const OwnedDog = withOwner('swyx')(Dog)
const OwnedDog = withOwner('swyx')(Dog);
```

We want to type `withOwner` such that it will pass through the types of any component like `Dog`, into the type of `OwnedDog`, minus the `owner` property it injects:

```tsx
typeof OwnedDog // we want this to be equal to { name: string }
typeof OwnedDog; // we want this to be equal to { name: string }

<Dog name="fido" owner="swyx" /> // this should be fine
<OwnedDog name="fido" owner="swyx" /> // this should have a typeError
<OwnedDog name="fido" /> // this should be fine
<Dog name="fido" owner="swyx" />; // this should be fine
<OwnedDog name="fido" owner="swyx" />; // this should have a typeError
<OwnedDog name="fido" />; // this should be fine

// and the HOC should be reusable for completely different prop types!

type CatProps {
lives: number
owner: string
}
function Cat({lives, owner}: CatProps) {
return <div> Meow: {lives}, Owner: {owner}</div>
type CatProps = {
lives: number;
owner: string;
};
function Cat({ lives, owner }: CatProps) {
return (
<div>
{' '}
Meow: {lives}, Owner: {owner}
</div>
);
}

const OwnedCat = withOwner('swyx')(Cat)
const OwnedCat = withOwner('swyx')(Cat);

<Cat lives={9} owner="swyx" /> // this should be fine
<OwnedCat lives={9} owner="swyx" /> // this should have a typeError
<OwnedCat lives={9} /> // this should be fine
<Cat lives={9} owner="swyx" />; // this should be fine
<OwnedCat lives={9} owner="swyx" />; // this should have a typeError
<OwnedCat lives={9} />; // this should be fine
```

So how do we type `withOwner`?
Expand All @@ -396,16 +401,17 @@ So how do we type `withOwner`?

```tsx
function withOwner(owner: string) {
return function<T extends { owner: string }> (Component: React.ComponentType<T>) {
return function (props: Omit<T, 'owner'>): React.ReactNode {
return <Component owner={owner} {...props} />
}
}
return function<T extends { owner: string }>(
Component: React.ComponentType<T>
) {
return function(props: Omit<T, 'owner'>): React.ReactNode {
return <Component owner={owner} {...props} />;
};
};
}
```

*Note: above is an incomplete, nonworking example. PR a fix!*

_Note: above is an incomplete, nonworking example. PR a fix!_

## Good articles

Expand Down
3 changes: 1 addition & 2 deletions MIGRATING.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ Misc tips/approaches successful companies have taken
- pick ESLint over TSLint (source: [ESLint](https://eslint.org/blog/2019/01/future-typescript-eslint) and [TS Roadmap](https://github.com/Microsoft/TypeScript/issues/29288))
- New code must always be written in TypeScript. No exceptions. For existing code: If your task requires you to change JavaScript code, you need to rewrite it. (Source: [Hootsuite][hootsuite])


<details>
<summary>
<b>
Expand Down Expand Up @@ -109,7 +108,7 @@ Problems to be aware of:
- If you have an error in the jsdoc, you get no warning/error. TS just silently doesn't type annotate the function.
- [casting can be verbose](https://twitter.com/bahmutov/status/1089229349637754880)

(*thanks [Gil Tayar](https://twitter.com/giltayar/status/1089228919260221441) and [Gleb Bahmutov](https://twitter.com/bahmutov/status/1089229196247908353) for sharing above commentary*)
(_thanks [Gil Tayar](https://twitter.com/giltayar/status/1089228919260221441) and [Gleb Bahmutov](https://twitter.com/bahmutov/status/1089229196247908353) for sharing above commentary_)

## From JS

Expand Down
Loading