Skip to content

Commit 7eb969b

Browse files
authored
Apply lint rule @typescript-eslint/no-empty-object-type (#29159)
* Apply lint rule @typescript-eslint/no-empty-object-type To avoid the footgun that is https://www.totaltypescript.com/the-empty-object-type-in-typescript Signed-off-by: Michael Telatynski <[email protected]> * Iterate Signed-off-by: Michael Telatynski <[email protected]> --------- Signed-off-by: Michael Telatynski <[email protected]>
1 parent 8cae1e9 commit 7eb969b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+158
-159
lines changed

.eslintrc.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,13 @@ module.exports = {
200200
"@typescript-eslint/ban-ts-comment": "off",
201201
// We're okay with assertion errors when we ask for them
202202
"@typescript-eslint/no-non-null-assertion": "off",
203-
// We do this sometimes to brand interfaces
204-
"@typescript-eslint/no-empty-object-type": "off",
203+
"@typescript-eslint/no-empty-object-type": [
204+
"error",
205+
{
206+
// We do this sometimes to brand interfaces
207+
allowInterfaces: "with-single-extends",
208+
},
209+
],
205210
},
206211
},
207212
// temporary override for offending icon require files
@@ -247,6 +252,7 @@ module.exports = {
247252
// We don't need super strict typing in test utilities
248253
"@typescript-eslint/explicit-function-return-type": "off",
249254
"@typescript-eslint/explicit-member-accessibility": "off",
255+
"@typescript-eslint/no-empty-object-type": "off",
250256

251257
// Jest/Playwright specific
252258

playwright/pages/client.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import type {
2525
StateEvents,
2626
TimelineEvents,
2727
AccountDataEvents,
28+
EmptyObject,
2829
} from "matrix-js-sdk/src/matrix";
2930
import type { RoomMessageEventContent } from "matrix-js-sdk/src/types";
3031
import { Credentials } from "../plugins/homeserver";
@@ -363,7 +364,7 @@ export class Client {
363364
event: JSHandle<MatrixEvent>,
364365
receiptType?: ReceiptType,
365366
unthreaded?: boolean,
366-
): Promise<{}> {
367+
): Promise<EmptyObject> {
367368
const client = await this.prepareClient();
368369
return client.evaluate(
369370
(client, { event, receiptType, unthreaded }) => {
@@ -386,7 +387,7 @@ export class Client {
386387
* @return {Promise} Resolves: {} an empty object.
387388
* @return {module:http-api.MatrixError} Rejects: with an error response.
388389
*/
389-
public async setDisplayName(name: string): Promise<{}> {
390+
public async setDisplayName(name: string): Promise<EmptyObject> {
390391
const client = await this.prepareClient();
391392
return client.evaluate(async (cli: MatrixClient, name) => cli.setDisplayName(name), name);
392393
}
@@ -397,7 +398,7 @@ export class Client {
397398
* @return {Promise} Resolves: {} an empty object.
398399
* @return {module:http-api.MatrixError} Rejects: with an error response.
399400
*/
400-
public async setAvatarUrl(url: string): Promise<{}> {
401+
public async setAvatarUrl(url: string): Promise<EmptyObject> {
401402
const client = await this.prepareClient();
402403
return client.evaluate(async (cli: MatrixClient, url) => cli.setAvatarUrl(url), url);
403404
}

src/@types/diff-dom.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ declare module "diff-dom" {
1818
newValue: HTMLElement | string;
1919
}
2020

21+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
2122
interface IOpts {}
2223

2324
export class DiffDOM {

src/@types/matrix-js-sdk.d.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type { BLURHASH_FIELD } from "../utils/image-media";
1111
import type { JitsiCallMemberEventType, JitsiCallMemberContent } from "../call-types";
1212
import type { ILayoutStateEvent, WIDGET_LAYOUT_EVENT_TYPE } from "../stores/widgets/types";
1313
import type { EncryptedFile } from "matrix-js-sdk/src/types";
14+
import type { EmptyObject } from "matrix-js-sdk/src/matrix";
1415
import type { DeviceClientInformation } from "../utils/device/types.ts";
1516
import type { UserWidget } from "../utils/WidgetUtils-types.ts";
1617

@@ -35,7 +36,7 @@ declare module "matrix-js-sdk/src/types" {
3536
[JitsiCallMemberEventType]: JitsiCallMemberContent;
3637

3738
// Unstable widgets state events
38-
"im.vector.modular.widgets": IWidget | {};
39+
"im.vector.modular.widgets": IWidget | EmptyObject;
3940
[WIDGET_LAYOUT_EVENT_TYPE]: ILayoutStateEvent;
4041

4142
// Element custom state events
@@ -104,6 +105,6 @@ declare module "matrix-js-sdk/src/types" {
104105
// https://github.com/matrix-org/matrix-doc/pull/3246
105106
waveform?: number[];
106107
};
107-
"org.matrix.msc3245.voice"?: {};
108+
"org.matrix.msc3245.voice"?: EmptyObject;
108109
}
109110
}

src/@types/react.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import React, { PropsWithChildren } from "react";
1010

1111
declare module "react" {
1212
// Fix forwardRef types for Generic components - https://stackoverflow.com/a/58473012
13-
function forwardRef<T, P = {}>(
13+
function forwardRef<T, P extends object>(
1414
render: (props: PropsWithChildren<P>, ref: React.ForwardedRef<T>) => React.ReactElement | null,
1515
): (props: P & React.RefAttributes<T>) => React.ReactElement | null;
1616

src/AddThreepid.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ export default class AddThreepid {
249249
* @param {{type: string, session?: string}} auth UI auth object
250250
* @return {Promise<Object>} Response from /3pid/add call (in current spec, an empty object)
251251
*/
252+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
252253
private makeAddThreepidOnlyRequest = (auth?: IAddThreePidOnlyBody["auth"] | null): Promise<{}> => {
253254
return this.matrixClient.addThreePidOnly({
254255
sid: this.sessionId!,

src/WorkerManager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { defer, IDeferred } from "matrix-js-sdk/src/utils";
1010

1111
import { WorkerPayload } from "./workers/worker";
1212

13-
export class WorkerManager<Request extends {}, Response> {
13+
export class WorkerManager<Request extends object, Response> {
1414
private readonly worker: Worker;
1515
private seq = 0;
1616
private pendingDeferredMap = new Map<number, IDeferred<Response>>();

src/autocomplete/QueryMatcher.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { removeHiddenChars } from "matrix-js-sdk/src/utils";
1414
import { TimelineRenderingType } from "../contexts/RoomContext";
1515
import { Leaves } from "../@types/common";
1616

17-
interface IOptions<T extends {}> {
17+
interface IOptions<T extends object> {
1818
keys: Array<Leaves<T>>;
1919
funcs?: Array<(o: T) => string | string[]>;
2020
shouldMatchWordsOnly?: boolean;
@@ -37,7 +37,7 @@ interface IOptions<T extends {}> {
3737
* @param {function[]} options.funcs List of functions that when called with the
3838
* object as an arg will return a string to use as an index
3939
*/
40-
export default class QueryMatcher<T extends {}> {
40+
export default class QueryMatcher<T extends object> {
4141
private _options: IOptions<T>;
4242
private _items = new Map<string, { object: T; keyWeight: number }[]>();
4343

src/components/structures/AutoHideScrollbar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import classNames from "classnames";
1111
import React, { HTMLAttributes, ReactHTML, ReactNode, WheelEvent } from "react";
1212

1313
type DynamicHtmlElementProps<T extends keyof JSX.IntrinsicElements> =
14-
JSX.IntrinsicElements[T] extends HTMLAttributes<{}> ? DynamicElementProps<T> : DynamicElementProps<"div">;
14+
JSX.IntrinsicElements[T] extends HTMLAttributes<object> ? DynamicElementProps<T> : DynamicElementProps<"div">;
1515
type DynamicElementProps<T extends keyof JSX.IntrinsicElements> = Partial<Omit<JSX.IntrinsicElements[T], "ref">>;
1616

1717
export type IProps<T extends keyof JSX.IntrinsicElements> = Omit<DynamicHtmlElementProps<T>, "onScroll"> & {

src/components/structures/NonUrgentToastContainer.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,18 @@ Please see LICENSE files in the repository root for full details.
77
*/
88

99
import * as React from "react";
10+
import { EmptyObject } from "matrix-js-sdk/src/matrix";
1011

1112
import { ComponentClass } from "../../@types/common";
1213
import NonUrgentToastStore from "../../stores/NonUrgentToastStore";
1314
import { UPDATE_EVENT } from "../../stores/AsyncStore";
1415

15-
interface IProps {}
16-
1716
interface IState {
1817
toasts: ComponentClass[];
1918
}
2019

21-
export default class NonUrgentToastContainer extends React.PureComponent<IProps, IState> {
22-
public constructor(props: IProps) {
20+
export default class NonUrgentToastContainer extends React.PureComponent<EmptyObject, IState> {
21+
public constructor(props: EmptyObject) {
2322
super(props);
2423

2524
this.state = {

src/components/structures/ToastContainer.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Please see LICENSE files in the repository root for full details.
99
import * as React from "react";
1010
import classNames from "classnames";
1111
import { Text } from "@vector-im/compound-web";
12+
import { EmptyObject } from "matrix-js-sdk/src/matrix";
1213

1314
import ToastStore, { IToast } from "../../stores/ToastStore";
1415

@@ -17,8 +18,8 @@ interface IState {
1718
countSeen: number;
1819
}
1920

20-
export default class ToastContainer extends React.Component<{}, IState> {
21-
public constructor(props: {}) {
21+
export default class ToastContainer extends React.Component<EmptyObject, IState> {
22+
public constructor(props: EmptyObject) {
2223
super(props);
2324
this.state = {
2425
toasts: ToastStore.sharedInstance().getToasts(),

src/components/structures/auth/header/AuthHeaderProvider.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ interface AuthHeaderAction {
2424

2525
export type AuthHeaderReducer = Reducer<ComponentProps<typeof AuthHeaderModifier>[], AuthHeaderAction>;
2626

27-
export function AuthHeaderProvider({ children }: PropsWithChildren<{}>): JSX.Element {
27+
export function AuthHeaderProvider({ children }: PropsWithChildren): JSX.Element {
2828
const [state, dispatch] = useReducer<AuthHeaderReducer>(
2929
(state: ComponentProps<typeof AuthHeaderModifier>[], action: AuthHeaderAction) => {
3030
switch (action.type) {

src/components/views/audio_messages/Waveform.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ interface IProps {
1818
progress: number; // percent complete, 0-1, default 100%
1919
}
2020

21-
interface IState {}
22-
2321
/**
2422
* A simple waveform component. This renders bars (centered vertically) for each
2523
* height provided in the component properties. Updating the properties will update
@@ -28,7 +26,7 @@ interface IState {}
2826
* For CSS purposes, a mx_Waveform_bar_100pct class is added when the bar should be
2927
* "filled", as a demonstration of the progress property.
3028
*/
31-
export default class Waveform extends React.PureComponent<IProps, IState> {
29+
export default class Waveform extends React.PureComponent<IProps> {
3230
public static defaultProps = {
3331
progress: 1,
3432
};

src/components/views/auth/InteractiveAuthEntryComponents.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -894,7 +894,7 @@ export class SSOAuthEntry extends React.Component<ISSOAuthEntryProps, ISSOAuthEn
894894
}
895895
}
896896

897-
export class FallbackAuthEntry<T = {}> extends React.Component<IAuthEntryProps & T> {
897+
export class FallbackAuthEntry<T extends object> extends React.Component<IAuthEntryProps & T> {
898898
protected popupWindow: Window | null;
899899
protected fallbackButton = createRef<HTMLDivElement>();
900900

src/components/views/auth/Welcome.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Please see LICENSE files in the repository root for full details.
77

88
import React from "react";
99
import classNames from "classnames";
10+
import { EmptyObject } from "matrix-js-sdk/src/matrix";
1011

1112
import SdkConfig from "../../../SdkConfig";
1213
import AuthPage from "./AuthPage";
@@ -16,9 +17,7 @@ import LanguageSelector from "./LanguageSelector";
1617
import EmbeddedPage from "../../structures/EmbeddedPage";
1718
import { MATRIX_LOGO_HTML } from "../../structures/static-page-vars";
1819

19-
interface IProps {}
20-
21-
export default class Welcome extends React.PureComponent<IProps> {
20+
export default class Welcome extends React.PureComponent<EmptyObject> {
2221
public render(): React.ReactNode {
2322
const pagesConfig = SdkConfig.getObject("embedded_pages");
2423
let pageUrl: string | undefined;

src/components/views/elements/EditableItemList.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ interface IProps {
101101
onNewItemChanged?(item: string): void;
102102
}
103103

104-
export default class EditableItemList<P = {}> extends React.PureComponent<IProps & P> {
104+
export default class EditableItemList<P extends object> extends React.PureComponent<IProps & P> {
105105
protected onItemAdded = (e: ButtonEvent): void => {
106106
e.stopPropagation();
107107
e.preventDefault();

src/components/views/elements/StyledCheckbox.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ interface IProps extends React.InputHTMLAttributes<HTMLInputElement> {
2121
id?: string;
2222
}
2323

24-
interface IState {}
25-
26-
export default class StyledCheckbox extends React.PureComponent<IProps, IState> {
24+
export default class StyledCheckbox extends React.PureComponent<IProps> {
2725
private id: string;
2826

2927
public static readonly defaultProps = {

src/components/views/elements/StyledRadioButton.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ interface IProps extends React.InputHTMLAttributes<HTMLInputElement> {
1818
childrenInLabel?: boolean;
1919
}
2020

21-
interface IState {}
22-
23-
export default class StyledRadioButton extends React.PureComponent<IProps, IState> {
21+
export default class StyledRadioButton extends React.PureComponent<IProps> {
2422
public static readonly defaultProps = {
2523
className: "",
2624
childrenInLabel: true,

src/components/views/rooms/Autocomplete.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
66
Please see LICENSE files in the repository root for full details.
77
*/
88

9-
import React, { createRef, KeyboardEvent, RefObject } from "react";
9+
import React, { createRef, RefObject } from "react";
1010
import classNames from "classnames";
1111
import { flatMap } from "lodash";
1212
import { Room } from "matrix-js-sdk/src/matrix";
@@ -206,7 +206,7 @@ export default class Autocomplete extends React.PureComponent<IProps, IState> {
206206
this.setSelection(1 + index);
207207
}
208208

209-
public onEscape(e: KeyboardEvent): boolean | undefined {
209+
public onEscape(e: KeyboardEvent | React.KeyboardEvent): boolean | undefined {
210210
const completionCount = this.countCompletions();
211211
if (completionCount === 0) {
212212
// autocomplete is already empty, so don't preventDefault

src/components/views/rooms/RoomBreadcrumbs.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
77
*/
88

99
import React, { createRef } from "react";
10-
import { Room } from "matrix-js-sdk/src/matrix";
10+
import { EmptyObject, Room } from "matrix-js-sdk/src/matrix";
1111
import { CSSTransition } from "react-transition-group";
1212

1313
import { BreadcrumbsStore } from "../../../stores/BreadcrumbsStore";
@@ -21,8 +21,6 @@ import { Action } from "../../../dispatcher/actions";
2121
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
2222
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
2323

24-
interface IProps {}
25-
2624
interface IState {
2725
// Both of these control the animation for the breadcrumbs. For details on the
2826
// actual animation, see the CSS.
@@ -59,11 +57,11 @@ const RoomBreadcrumbTile: React.FC<{ room: Room; onClick: (ev: ButtonEvent) => v
5957
);
6058
};
6159

62-
export default class RoomBreadcrumbs extends React.PureComponent<IProps, IState> {
60+
export default class RoomBreadcrumbs extends React.PureComponent<EmptyObject, IState> {
6361
private unmounted = false;
6462
private toolbar = createRef<HTMLDivElement>();
6563

66-
public constructor(props: IProps) {
64+
public constructor(props: EmptyObject) {
6765
super(props);
6866

6967
this.state = {

src/components/views/rooms/wysiwyg_composer/hooks/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export function handleEventWithAutocomplete(
9292
handled = true;
9393
break;
9494
case KeyBindingAction.CancelAutocomplete:
95-
autocompleteRef.current.onEscape(event as {} as React.KeyboardEvent);
95+
autocompleteRef.current.onEscape(event);
9696
handled = true;
9797
break;
9898
default:

src/components/views/settings/CrossSigningPanel.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
77
*/
88

99
import React from "react";
10-
import { ClientEvent, MatrixEvent } from "matrix-js-sdk/src/matrix";
10+
import { ClientEvent, EmptyObject, MatrixEvent } from "matrix-js-sdk/src/matrix";
1111
import { logger } from "matrix-js-sdk/src/logger";
1212
import { CryptoEvent } from "matrix-js-sdk/src/crypto-api";
1313

@@ -33,10 +33,10 @@ interface IState {
3333
crossSigningReady?: boolean;
3434
}
3535

36-
export default class CrossSigningPanel extends React.PureComponent<{}, IState> {
36+
export default class CrossSigningPanel extends React.PureComponent<EmptyObject, IState> {
3737
private unmounted = false;
3838

39-
public constructor(props: {}) {
39+
public constructor(props: EmptyObject) {
4040
super(props);
4141

4242
this.state = {

src/components/views/settings/CryptographyPanel.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details.
88

99
import React, { lazy } from "react";
1010
import { logger } from "matrix-js-sdk/src/logger";
11+
import { EmptyObject } from "matrix-js-sdk/src/matrix";
1112

1213
import { _t } from "../../../languageHandler";
1314
import Modal from "../../../Modal";
@@ -19,8 +20,6 @@ import { SettingLevel } from "../../../settings/SettingLevel";
1920
import { SettingsSubsection, SettingsSubsectionText } from "./shared/SettingsSubsection";
2021
import MatrixClientContext from "../../../contexts/MatrixClientContext";
2122

22-
interface IProps {}
23-
2423
interface IState {
2524
/** The device's base64-encoded Ed25519 identity key, or:
2625
*
@@ -30,11 +29,11 @@ interface IState {
3029
deviceIdentityKey: string | undefined | null;
3130
}
3231

33-
export default class CryptographyPanel extends React.Component<IProps, IState> {
32+
export default class CryptographyPanel extends React.Component<EmptyObject, IState> {
3433
public static contextType = MatrixClientContext;
3534
declare public context: React.ContextType<typeof MatrixClientContext>;
3635

37-
public constructor(props: IProps, context: React.ContextType<typeof MatrixClientContext>) {
36+
public constructor(props: EmptyObject, context: React.ContextType<typeof MatrixClientContext>) {
3837
super(props);
3938

4039
if (!context.getCrypto()) {

0 commit comments

Comments
 (0)