Skip to content

Commit

Permalink
refactor: fix more type-aware linting errors (#7479)
Browse files Browse the repository at this point in the history
  • Loading branch information
Josh-Cena authored May 24, 2022
1 parent bf1513a commit 624735b
Show file tree
Hide file tree
Showing 51 changed files with 195 additions and 192 deletions.
4 changes: 2 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ module.exports = {
'no-restricted-exports': OFF,
'no-restricted-properties': [
ERROR,
...[
.../** @type {[string, string][]} */ ([
// TODO: TS doesn't make Boolean a narrowing function yet,
// so filter(Boolean) is problematic type-wise
// ['compact', 'Array#filter(Boolean)'],
Expand Down Expand Up @@ -114,7 +114,7 @@ module.exports = {
['take', 'Array#slice(0, n)'],
['takeRight', 'Array#slice(-n)'],
['tail', 'Array#slice(1)'],
].map(([property, alternative]) => ({
]).map(([property, alternative]) => ({
object: '_',
property,
message: `Use ${alternative} instead.`,
Expand Down
7 changes: 4 additions & 3 deletions admin/scripts/generateExamples.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@ async function generateTemplateExample(template) {
`npm init docusaurus@latest examples/${template} ${command}`,
);

const templatePackageJson = await fs.readJSON(
`examples/${template}/package.json`,
);
const templatePackageJson =
await /** @type {Promise<import("../../packages/create-docusaurus/templates/classic/package.json") & { scripts: { [name: string]: string }; description: string }>} */ (
fs.readJSON(`examples/${template}/package.json`)
);

// Attach the dev script which would be used in code sandbox by default
templatePackageJson.scripts.dev = 'docusaurus start';
Expand Down
4 changes: 3 additions & 1 deletion packages/create-docusaurus/bin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import logger from '@docusaurus/logger';
import semver from 'semver';
import {program} from 'commander';

const packageJson = createRequire(import.meta.url)('../package.json');
const packageJson = /** @type {import("../package.json")} */ (
createRequire(import.meta.url)('../package.json')
);
const requiredVersion = packageJson.engines.node;

if (!semver.satisfies(process.version, requiredVersion)) {
Expand Down
2 changes: 1 addition & 1 deletion packages/create-docusaurus/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ async function askForPackageManagerChoice(): Promise<PackageManager> {
logger.info`Falling back to name=${defaultPackageManager}`;
},
},
)) as {packageManager: PackageManager}
)) as {packageManager?: PackageManager}
).packageManager ?? defaultPackageManager
);
}
Expand Down
6 changes: 4 additions & 2 deletions packages/docusaurus-migrate/bin/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import semver from 'semver';
import cli from 'commander';

const moduleRequire = createRequire(import.meta.url);
const requiredVersion = moduleRequire('../package.json').engines.node;
const requiredVersion = /** @type {import("../package.json")} */ (
moduleRequire('../package.json')
).engines.node;

if (!semver.satisfies(process.version, requiredVersion)) {
logger.error('Minimum Node.js version not met :(');
Expand All @@ -25,7 +27,7 @@ if (!semver.satisfies(process.version, requiredVersion)) {

// See https://github.com/facebook/docusaurus/pull/6860
const {migrateDocusaurusProject, migrateMDToMDX} =
moduleRequire('../lib/index.js');
/** @type {import("../lib/index.js")} */ (moduleRequire('../lib/index.js'));

cli
.command('migrate [siteDir] [newDir]')
Expand Down
13 changes: 12 additions & 1 deletion packages/docusaurus-module-type-aliases/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,16 +323,27 @@ declare module '@docusaurus/renderRoutes' {
declare module '@docusaurus/useGlobalData' {
import type {GlobalData, UseDataOptions} from '@docusaurus/types';

export function useAllPluginInstancesData(
pluginName: string,
options: {failfast: true},
): GlobalData[string];

export function useAllPluginInstancesData(
pluginName: string,
options?: UseDataOptions,
): GlobalData[string] | undefined;

export function usePluginData(
pluginName: string,
pluginId: string | undefined,
options: {failfast: true},
): NonNullable<GlobalData[string][string]>;

export function usePluginData(
pluginName: string,
pluginId?: string,
options?: UseDataOptions,
): GlobalData[string][string] | undefined;
): GlobalData[string][string];

export default function useGlobalData(): GlobalData;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,9 @@ describe.each(['atom', 'rss', 'json'])('%s', (feedType) => {
} as PluginOptions,
);

expect(fsMock.mock.calls.map((call) => call[1])).toMatchSnapshot();
expect(
fsMock.mock.calls.map((call) => call[1] as string),
).toMatchSnapshot();
fsMock.mockClear();
});
});
10 changes: 3 additions & 7 deletions packages/docusaurus-plugin-content-docs/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
getVersionDocsDirPath,
getVersionSidebarsPath,
getDocsDirPathLocalized,
readVersionsFile,
} from './versions/files';
import {validateVersionName} from './versions/validation';
import {loadSidebarsFileUnsafe} from './sidebars';
Expand Down Expand Up @@ -69,12 +70,7 @@ export async function cliDocsVersionCommand(
throw err;
}

// Load existing versions.
let versions: string[] = [];
const versionsJSONFile = getVersionsFilePath(siteDir, pluginId);
if (await fs.pathExists(versionsJSONFile)) {
versions = await fs.readJSON(versionsJSONFile);
}
const versions = (await readVersionsFile(siteDir, pluginId)) ?? [];

// Check if version already exists.
if (versions.includes(version)) {
Expand Down Expand Up @@ -137,7 +133,7 @@ export async function cliDocsVersionCommand(
// Update versions.json file.
versions.unshift(version);
await fs.outputFile(
versionsJSONFile,
getVersionsFilePath(siteDir, pluginId),
`${JSON.stringify(versions, null, 2)}\n`,
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export function getVersionsFilePath(siteDir: string, pluginId: string): string {
* @throws Throws if validation fails, i.e. `versions.json` doesn't contain an
* array of valid version names.
*/
async function readVersionsFile(
export async function readVersionsFile(
siteDir: string,
pluginId: string,
): Promise<string[] | null> {
Expand Down
5 changes: 3 additions & 2 deletions packages/docusaurus-theme-classic/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ import type webpack from 'webpack';
const requireFromDocusaurusCore = createRequire(
require.resolve('@docusaurus/core/package.json'),
);
const ContextReplacementPlugin: typeof webpack.ContextReplacementPlugin =
requireFromDocusaurusCore('webpack/lib/ContextReplacementPlugin');
const ContextReplacementPlugin = requireFromDocusaurusCore(
'webpack/lib/ContextReplacementPlugin',
) as typeof webpack.ContextReplacementPlugin;

// Need to be inlined to prevent dark mode FOUC
// Make sure the key is the same as the one in `/theme/hooks/useTheme.js`
Expand Down
3 changes: 1 addition & 2 deletions packages/docusaurus-theme-classic/src/theme-classic.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -816,7 +816,6 @@ declare module '@theme/NavbarItem/NavbarNavLink' {

declare module '@theme/NavbarItem/DropdownNavbarItem' {
import type {Props as NavbarNavLinkProps} from '@theme/NavbarItem/NavbarNavLink';

import type {LinkLikeNavbarItemProps} from '@theme/NavbarItem';

export type DesktopOrMobileNavBarItemProps = NavbarNavLinkProps & {
Expand Down Expand Up @@ -976,7 +975,7 @@ declare module '@theme/NavbarItem' {
} & SearchNavbarItemProps)
);

export type Types = Props['type'];
export type NavbarItemType = Props['type'];

export default function NavbarItem(props: Props): JSX.Element;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import Details from '@theme/Details';
import type {Props} from '@theme/MDXComponents/Details';

export default function MDXDetails(props: Props): JSX.Element {
const items = React.Children.toArray(props.children) as ReactElement[];
const items = React.Children.toArray(props.children);
// Split summary item from the rest to pass it as a separate prop to the
// Details theme component
const summary: ReactElement<ComponentProps<'summary'>> | undefined =
items.find((item) => item?.props?.mdxType === 'summary');
const summary = items.find(
(item): item is ReactElement<ComponentProps<'summary'>> =>
React.isValidElement(item) && item.props?.mdxType === 'summary',
);
const children = <>{items.filter((item) => item !== summary)}</>;

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import type {Props} from '@theme/MDXComponents/Head';

// MDX elements are wrapped through the MDX pragma. In some cases (notably usage
// with Head/Helmet) we need to unwrap those elements.
function unwrapMDXElement(element: ReactElement) {
if (element?.props?.mdxType && element?.props?.originalType) {
function unwrapMDXElement(
element: ReactElement<{mdxType?: string; originalType?: string} | undefined>,
) {
if (element.props?.mdxType && element.props.originalType) {
const {mdxType, originalType, ...newProps} = element.props;
return React.createElement(element.props.originalType, newProps);
}
Expand All @@ -21,7 +23,7 @@ function unwrapMDXElement(element: ReactElement) {

export default function MDXHead(props: Props): JSX.Element {
const unwrappedChildren = React.Children.map(props.children, (child) =>
unwrapMDXElement(child as ReactElement),
React.isValidElement(child) ? unwrapMDXElement(child) : child,
);
return (
<Head {...(props as ComponentProps<typeof Head>)}>{unwrappedChildren}</Head>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export default function MDXPre(props: Props): JSX.Element {
<CodeBlock
// If this pre is created by a ``` fenced codeblock, unwrap the children
{...(isValidElement(props.children) &&
props.children.props.originalType === 'code'
? props.children?.props
props.children.props?.originalType === 'code'
? props.children.props
: {...props})}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@ import {
useNavbarMobileSidebar,
useThemeConfig,
} from '@docusaurus/theme-common';
import NavbarItem from '@theme/NavbarItem';
import NavbarItem, {type Props as NavbarItemConfig} from '@theme/NavbarItem';
import NavbarColorModeToggle from '@theme/Navbar/ColorModeToggle';
import SearchBar from '@theme/SearchBar';
import NavbarMobileSidebarToggle from '@theme/Navbar/MobileSidebar/Toggle';
import NavbarLogo from '@theme/Navbar/Logo';
import NavbarSearch from '@theme/Navbar/Search';
import type {Props as NavbarItemConfig} from '@theme/NavbarItem';

import styles from './styles.module.css';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@

import React from 'react';
import {useNavbarMobileSidebar, useThemeConfig} from '@docusaurus/theme-common';
import NavbarItem from '@theme/NavbarItem';
import type {Props as NavbarItemConfig} from '@theme/NavbarItem';
import NavbarItem, {type Props as NavbarItemConfig} from '@theme/NavbarItem';

function useNavbarItems() {
// TODO temporary casting until ThemeConfig type is improved
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ export default function DocsVersionDropdownNavbarItem({
// We try to link to the same doc, in another version
// When not possible, fallback to the "main doc" of the version
const versionDoc =
activeDocContext?.alternateDocVersions[version.name] ??
activeDocContext.alternateDocVersions[version.name] ??
getVersionMainDoc(version);
return {
isNavLink: true,
label: version.label,
to: versionDoc.path,
isActive: () => version === activeDocContext?.activeVersion,
isActive: () => version === activeDocContext.activeVersion,
onClick: () => savePreferredVersionName(version.name),
};
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@ import {
useLocalPathname,
} from '@docusaurus/theme-common';
import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink';
import NavbarItem from '@theme/NavbarItem';
import NavbarItem, {type LinkLikeNavbarItemProps} from '@theme/NavbarItem';
import type {
DesktopOrMobileNavBarItemProps,
Props,
} from '@theme/NavbarItem/DropdownNavbarItem';
import type {LinkLikeNavbarItemProps} from '@theme/NavbarItem';

const dropdownLinkActiveClass = 'dropdown__link--active';

Expand Down
27 changes: 9 additions & 18 deletions packages/docusaurus-theme-classic/src/theme/NavbarItem/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,22 @@

import React from 'react';
import ComponentTypes from '@theme/NavbarItem/ComponentTypes';
import {type Props as DropdownNavbarItemProps} from '@theme/NavbarItem/DropdownNavbarItem';
import type {Types, Props} from '@theme/NavbarItem';
import type {NavbarItemType, Props} from '@theme/NavbarItem';

const getNavbarItemComponent = (type: NonNullable<Types>) => {
const component = ComponentTypes[type];
if (!component) {
throw new Error(`No NavbarItem component found for type "${type}".`);
}
return component;
};

function getComponentType(type: Types, isDropdown: boolean) {
function normalizeComponentType(type: NavbarItemType, props: object) {
// Backward compatibility: navbar item with no type set
// but containing dropdown items should use the type "dropdown"
if (!type || type === 'default') {
return isDropdown ? 'dropdown' : 'default';
return 'items' in props ? 'dropdown' : 'default';
}
return type as NonNullable<Types>;
return type;
}

export default function NavbarItem({type, ...props}: Props): JSX.Element {
const componentType = getComponentType(
type,
(props as DropdownNavbarItemProps).items !== undefined,
);
const NavbarItemComponent = getNavbarItemComponent(componentType);
const componentType = normalizeComponentType(type, props);
const NavbarItemComponent = ComponentTypes[componentType];
if (!NavbarItemComponent) {
throw new Error(`No NavbarItem component found for type "${type}".`);
}
return <NavbarItemComponent {...(props as never)} />;
}
6 changes: 3 additions & 3 deletions packages/docusaurus-theme-classic/src/theme/Tabs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ function TabsComponent(props: Props): JSX.Element {
? defaultValueProp
: defaultValueProp ??
children.find((child) => child.props.default)?.props.value ??
children[0]?.props.value;
children[0]!.props.value;
if (defaultValue !== null && !values.some((a) => a.value === defaultValue)) {
throw new Error(
`Docusaurus error: The <Tabs> has a defaultValue "${defaultValue}" but none of its children has the corresponding value. Available values are: ${values
Expand Down Expand Up @@ -126,12 +126,12 @@ function TabsComponent(props: Props): JSX.Element {
switch (event.key) {
case 'ArrowRight': {
const nextTab = tabRefs.indexOf(event.currentTarget) + 1;
focusElement = tabRefs[nextTab] || tabRefs[0]!;
focusElement = tabRefs[nextTab] ?? tabRefs[0]!;
break;
}
case 'ArrowLeft': {
const prevTab = tabRefs.indexOf(event.currentTarget) - 1;
focusElement = tabRefs[prevTab] || tabRefs[tabRefs.length - 1]!;
focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1]!;
break;
}
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export function Details({
}
}}>
{/* eslint-disable-next-line @docusaurus/no-untranslated-text */}
{summary || <summary>Details</summary>}
{summary ?? <summary>Details</summary>}

<Collapsible
lazy={false} // Content might matter for SEO in this case
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ export function useTOCHighlight(config: TOCHighlightConfig | undefined): void {
function updateLinkActiveClass(link: HTMLAnchorElement, active: boolean) {
if (active) {
if (lastActiveLinkRef.current && lastActiveLinkRef.current !== link) {
lastActiveLinkRef.current?.classList.remove(linkActiveClassName);
lastActiveLinkRef.current.classList.remove(linkActiveClassName);
}
link.classList.add(linkActiveClassName);
lastActiveLinkRef.current = link;
Expand Down
6 changes: 4 additions & 2 deletions packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export function parseCodeBlockTitle(metastring?: string): string {
}

export function containsLineNumbers(metastring?: string): boolean {
return metastring?.includes('showLineNumbers') || false;
return Boolean(metastring?.includes('showLineNumbers'));
}

/**
Expand Down Expand Up @@ -209,7 +209,9 @@ export function parseLines(
lineNumber += 1;
continue;
}
const directive = match.slice(1).find((item) => item !== undefined)!;
const directive = match
.slice(1)
.find((item: string | undefined) => item !== undefined)!;
if (lineToClassName[directive]) {
blocks[lineToClassName[directive]!]!.range += `${lineNumber},`;
} else if (blockStartToClassName[directive]) {
Expand Down
Loading

0 comments on commit 624735b

Please sign in to comment.