Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(v2): tighten up the TypeScript onboarding #3244

Merged
merged 3 commits into from
Aug 17, 2020
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: 5 additions & 0 deletions packages/docusaurus-module-type-aliases/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,10 @@
"publishConfig": {
"access": "public"
},
"devDependencies": {
"@types/react": "*",
"@types/react-helmet": "*",
"@types/react-router-dom": "*"
},
"license": "MIT"
}
36 changes: 36 additions & 0 deletions packages/docusaurus-module-type-aliases/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,42 @@ declare module '@theme-original/*';

declare module '@docusaurus/*';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This globally applies an any to all @docusaurus/* stuff, but because the following are more specific, then they get picked up as the module definition. This means as you add new things to the module TS users just get any, but then it can get filled in here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screen Shot 2020-08-08 at 11 26 02 AM


declare module '@docusaurus/Head' {
const helmet: typeof import('react-helmet').Helmet;
export default helmet;
}

declare module '@docusaurus/Link' {
type RRLinkProps = Partial<import('react-router-dom').LinkProps>;
type LinkProps = RRLinkProps & {
to?: string;
activeClassName?: string;
isNavLink?: boolean;
};
const Link: (props: LinkProps) => JSX.Element;
export default Link;
}

declare module '@docusaurus/router' {
export const Redirect: (props: {to: string}) => import('react').Component;
export function matchPath(
pathname: string,
opts: {path?: string; exact?: boolean; strict?: boolean},
): boolean;
export function useLocation(): Location;
}

declare module '@docusaurus/useDocusaurusContext' {
export default function (): any;
}

declare module '@docusaurus/useBaseUrl' {
export default function (
relativePath: string | undefined,
opts?: {absolute?: true; forcePrependBaseUrl?: true},
): string;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use the import("x") syntax, which means recommending people add the @types/x for them ahead of time

declare module '*.module.css' {
const classes: {readonly [key: string]: string};
export default classes;
Expand Down
2 changes: 1 addition & 1 deletion packages/docusaurus/src/client/PendingNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,4 @@ class PendingNavigation extends React.Component<Props, State> {
}
}

export default withRouter(PendingNavigation);
export default withRouter(PendingNavigation as any) as any;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

introducing @types/react-router-dom gave a fail here because the objects don't all match up - this is a known issue in the types for withRouter - it expects to be used as a decorator. I tried using a disable next error for this, but it still propagated into a bunch of places, so I just as any'd it

It previously was an any

2 changes: 1 addition & 1 deletion packages/docusaurus/src/client/exports/Link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ function Link({
{...props}
onMouseEnter={onMouseEnter}
innerRef={handleRef}
to={targetLink}
to={targetLink || ''}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to has always been a string | undefined and if it goes through the undefined path then it ends up a <a and not down this branch, as the linter doesn't allow a ! then I opted for the 'should never occur' || ""

// avoid "React does not recognize the `activeClassName` prop on a DOM element"
{...(isNavLink && {activeClassName})}
/>
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"lib": ["es2017","es2019.array", "DOM"],
"declaration": true,
"declarationMap": true,
"jsx": "react",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

optional and doesn't affect the output to my knowledge, but I get errors everywhere in vscode without it


/* Strict Type-Checking Options */
"strict": true,
Expand Down
25 changes: 5 additions & 20 deletions website/docs/typescript-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,22 @@ title: TypeScript Support

## Setup

Docusaurus supports writing and using TypeScript theme components. To start using TypeScript, add `@docusaurus/module-type-aliases` to your project:
Docusaurus supports writing and using TypeScript theme components. To start using TypeScript, add `@docusaurus/module-type-aliases` and some `@types` dependencies to your project:

```bash
npm install --save-dev typescript @docusaurus/module-type-aliases
npm install --save-dev typescript @docusaurus/module-type-aliases @types/react @types/react-router-dom @types/react-helmet @tsconfig/docusaurus
```
slorber marked this conversation as resolved.
Show resolved Hide resolved

Then add `tsconfig.json` to your project root with following content:
Then add `tsconfig.json` to your project root with the following content:

```json title="tsconfig.json"
{
"compilerOptions": {
"allowJs": true,
"esModuleInterop": true,
"jsx": "react",
"lib": ["DOM"],
"noEmit": true,
"noImplicitAny": false
},
"extends": "@tsconfig/docusaurus/tsconfig.json",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moves all these config options to tsconfig/bases#27 - then it's obvious what is framework vs project

"include": ["src/"]
}
```

Docusaurus doesn't use this `tsconfig.json` to compile your TypeScript. It is added just for a nicer Editor experience, although you can choose to run `tsc --noEmit` to type check your code for yourself.

Then add `types.d.ts` in your `src` folder with the following content:

```ts title="src/types.d.ts"
/// <reference types="@docusaurus/module-type-aliases" />
```

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed with https://github.com/tsconfig/bases/pull/28/files

This has one side-effect of encouraging people to be explicit in their global types, so for example if they wanted to add Jest tests, it would need to look like:

{
  "extends": "@tsconfig/docusaurus",
  "types": ["node",  "jest", "@docusaurus/module-type-aliases"],
  "include": ["src"]
}

But I imagine that this is the minority of folks, so I've left it off

This file makes TypeScript recognize various Docusaurus specific webpack aliases like `@theme`, `@docusaurus`, `@generated`.
Docusaurus doesn't use this `tsconfig.json` to compile your project. It is added just for a nicer Editor experience, although you can choose to run `tsc` to type check your code for yourself or on CI.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The config specifies noEmit - so no need to include it here


Now you can start writing TypeScript theme components.

Expand Down
16 changes: 16 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4108,6 +4108,13 @@
"@types/webpack" "*"
"@types/webpack-dev-server" "*"

"@types/react-helmet@*":
version "6.1.0"
resolved "https://registry.yarnpkg.com/@types/react-helmet/-/react-helmet-6.1.0.tgz#af586ed685f4905e2adc7462d1d65ace52beee7a"
integrity sha512-PYRoU1XJFOzQ3BHvWL1T8iDNbRjdMDJMT5hFmZKGbsq09kbSqJy61uwEpTrbTNWDopVphUT34zUSVLK9pjsgYQ==
dependencies:
"@types/react" "*"

"@types/react-helmet@^6.0.0":
version "6.0.0"
resolved "https://registry.yarnpkg.com/@types/react-helmet/-/react-helmet-6.0.0.tgz#5b74e44a12662ffb12d1c97ee702cf4e220958cf"
Expand All @@ -4132,6 +4139,15 @@
"@types/react" "*"
"@types/react-router" "*"

"@types/react-router-dom@*":
version "5.1.5"
resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.5.tgz#7c334a2ea785dbad2b2dcdd83d2cf3d9973da090"
integrity sha512-ArBM4B1g3BWLGbaGvwBGO75GNFbLDUthrDojV2vHLih/Tq8M+tgvY1DSwkuNrPSwdp/GUL93WSEpTZs8nVyJLw==
dependencies:
"@types/history" "*"
"@types/react" "*"
"@types/react-router" "*"

"@types/react-router@*":
version "5.1.7"
resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.7.tgz#e9d12ed7dcfc79187e4d36667745b69a5aa11556"
Expand Down