Comply with noImplicitAny (#9940)

* Stash noImplicitAny work

* Stash

* Fix imports

* Iterate

* Fix tests

* Delint

* Fix tests
This commit is contained in:
Michael Telatynski 2023-02-13 11:39:16 +00:00 committed by GitHub
parent ac7f69216e
commit 61a63e47f4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
359 changed files with 1621 additions and 1353 deletions

View file

@ -45,8 +45,7 @@ interface IProps {
}
interface IState {
// @ts-ignore - TS wants a string key, but we know better
apps: { [id: Container]: IApp[] };
apps: Partial<{ [id in Container]: IApp[] }>;
resizingVertical: boolean; // true when changing the height of the apps drawer
resizingHorizontal: boolean; // true when changing the distribution of the width between widgets
resizing: boolean;
@ -203,10 +202,9 @@ export default class AppsDrawer extends React.Component<IProps, IState> {
break;
}
};
// @ts-ignore - TS wants a string key, but we know better
private getApps = (): { [id: Container]: IApp[] } => {
// @ts-ignore
const appsDict: { [id: Container]: IApp[] } = {};
private getApps = (): Partial<{ [id in Container]: IApp[] }> => {
const appsDict: Partial<{ [id in Container]: IApp[] }> = {};
appsDict[Container.Top] = WidgetLayoutStore.instance.getContainerWidgets(this.props.room, Container.Top);
appsDict[Container.Center] = WidgetLayoutStore.instance.getContainerWidgets(this.props.room, Container.Center);
return appsDict;

View file

@ -57,7 +57,7 @@ export default class Autocomplete extends React.PureComponent<IProps, IState> {
public static contextType = RoomContext;
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {

View file

@ -55,7 +55,7 @@ export default class AuxPanel extends React.Component<IProps, IState> {
showApps: true,
};
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {
@ -76,7 +76,7 @@ export default class AuxPanel extends React.Component<IProps, IState> {
}
}
public shouldComponentUpdate(nextProps, nextState): boolean {
public shouldComponentUpdate(nextProps: IProps, nextState: IState): boolean {
return objectHasDiff(this.props, nextProps) || objectHasDiff(this.state, nextState);
}
@ -146,9 +146,9 @@ export default class AuxPanel extends React.Component<IProps, IState> {
);
}
let stateViews = null;
let stateViews: JSX.Element | null = null;
if (this.state.counters && SettingsStore.getValue("feature_state_counters")) {
const counters = [];
const counters: JSX.Element[] = [];
this.state.counters.forEach((counter, idx) => {
const title = counter.title;

View file

@ -32,7 +32,7 @@ import {
} from "../../../editor/operations";
import { getCaretOffsetAndText, getRangeForSelection } from "../../../editor/dom";
import Autocomplete, { generateCompletionDomId } from "../rooms/Autocomplete";
import { getAutoCompleteCreator, Part, Type } from "../../../editor/parts";
import { getAutoCompleteCreator, Part, SerializedPart, Type } from "../../../editor/parts";
import { parseEvent, parsePlainTextMessage } from "../../../editor/deserialize";
import { renderModel } from "../../../editor/render";
import SettingsStore from "../../../settings/SettingsStore";
@ -107,7 +107,7 @@ interface IProps {
initialCaret?: DocumentOffset;
disabled?: boolean;
onChange?();
onChange?(): void;
onPaste?(event: ClipboardEvent<HTMLDivElement>, model: EditorModel): boolean;
}
@ -140,7 +140,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
private readonly surroundWithHandle: string;
private readonly historyManager = new HistoryManager();
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {
showPillAvatar: SettingsStore.getValue("Pill.shouldShowPillAvatar"),
@ -367,7 +367,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
let parts: Part[];
if (partsText) {
const serializedTextParts = JSON.parse(partsText);
parts = serializedTextParts.map((p) => partCreator.deserializePart(p));
parts = serializedTextParts.map((p: SerializedPart) => partCreator.deserializePart(p));
} else {
parts = parsePlainTextMessage(plainText, partCreator, { shouldEscape: false });
}

View file

@ -29,7 +29,7 @@ import { getCaretOffsetAndText } from "../../../editor/dom";
import { htmlSerializeIfNeeded, textSerialize, containsEmote, stripEmoteCommand } from "../../../editor/serialize";
import { findEditableEvent } from "../../../utils/EventUtils";
import { parseEvent } from "../../../editor/deserialize";
import { CommandPartCreator, Part, PartCreator } from "../../../editor/parts";
import { CommandPartCreator, Part, PartCreator, SerializedPart } from "../../../editor/parts";
import EditorStateTransfer from "../../../utils/EditorStateTransfer";
import BasicMessageComposer, { REGEX_EMOTICON } from "./BasicMessageComposer";
import { CommandCategories } from "../../../SlashCommands";
@ -59,7 +59,7 @@ function getHtmlReplyFallback(mxEvent: MatrixEvent): string {
}
function getTextReplyFallback(mxEvent: MatrixEvent): string {
const body = mxEvent.getContent().body;
const body: string = mxEvent.getContent().body;
const lines = body.split("\n").map((l) => l.trim());
if (lines.length > 2 && lines[0].startsWith("> ") && lines[1].length === 0) {
return `${lines[0]}\n\n`;
@ -253,7 +253,7 @@ class EditMessageComposer extends React.Component<IEditMessageComposerProps, ISt
if (json) {
try {
const { parts: serializedParts } = JSON.parse(json);
const parts: Part[] = serializedParts.map((p) => partCreator.deserializePart(p));
const parts: Part[] = serializedParts.map((p: SerializedPart) => partCreator.deserializePart(p));
return parts;
} catch (e) {
logger.error("Error parsing editing state: ", e);

View file

@ -35,13 +35,15 @@ const PowerLabel: Record<PowerStatus, string> = {
[PowerStatus.Moderator]: _td("Mod"),
};
const PRESENCE_CLASS = {
export type PresenceState = "offline" | "online" | "unavailable";
const PRESENCE_CLASS: Record<PresenceState, string> = {
offline: "mx_EntityTile_offline",
online: "mx_EntityTile_online",
unavailable: "mx_EntityTile_unavailable",
};
function presenceClassForMember(presenceState: string, lastActiveAgo: number, showPresence: boolean): string {
function presenceClassForMember(presenceState: PresenceState, lastActiveAgo: number, showPresence: boolean): string {
if (showPresence === false) {
return "mx_EntityTile_online_beenactive";
}
@ -67,7 +69,7 @@ interface IProps {
title?: string;
avatarJsx?: JSX.Element; // <BaseAvatar />
className?: string;
presenceState?: string;
presenceState?: PresenceState;
presenceLastActiveAgo?: number;
presenceLastTs?: number;
presenceCurrentlyActive?: boolean;
@ -104,7 +106,7 @@ export default class EntityTile extends React.PureComponent<IProps, IState> {
}
public render(): JSX.Element {
const mainClassNames = {
const mainClassNames: Record<string, boolean> = {
mx_EntityTile: true,
mx_EntityTile_noHover: this.props.suppressOnHover,
};

View file

@ -617,8 +617,8 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
}
private propsEqual(objA: EventTileProps, objB: EventTileProps): boolean {
const keysA = Object.keys(objA);
const keysB = Object.keys(objB);
const keysA = Object.keys(objA) as Array<keyof EventTileProps>;
const keysB = Object.keys(objB) as Array<keyof EventTileProps>;
if (keysA.length !== keysB.length) {
return false;

View file

@ -37,7 +37,7 @@ interface IProps {
export default class LinkPreviewWidget extends React.Component<IProps> {
private image = createRef<HTMLImageElement>();
private onImageClick = (ev): void => {
private onImageClick = (ev: React.MouseEvent): void => {
const p = this.props.preview;
if (ev.button != 0 || ev.metaKey) return;
ev.preventDefault();

View file

@ -68,7 +68,8 @@ interface IState {
}
export default class MemberList extends React.Component<IProps, IState> {
private showPresence = true;
// XXX: exported for tests
public showPresence = true;
private mounted = false;
public static contextType = SDKContext;
@ -195,7 +196,8 @@ export default class MemberList extends React.Component<IProps, IState> {
{ leading: true, trailing: true },
);
private async updateListNow(showLoadingSpinner: boolean): Promise<void> {
// XXX: exported for tests
public async updateListNow(showLoadingSpinner?: boolean): Promise<void> {
if (!this.mounted) {
return;
}

View file

@ -28,10 +28,11 @@ import dis from "../../../dispatcher/dispatcher";
import { _t } from "../../../languageHandler";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import { Action } from "../../../dispatcher/actions";
import EntityTile, { PowerStatus } from "./EntityTile";
import EntityTile, { PowerStatus, PresenceState } from "./EntityTile";
import MemberAvatar from "./../avatars/MemberAvatar";
import DisambiguatedProfile from "../messages/DisambiguatedProfile";
import UserIdentifierCustomisations from "../../../customisations/UserIdentifier";
import { E2EState } from "./E2EIcon";
interface IProps {
member: RoomMember;
@ -40,7 +41,7 @@ interface IProps {
interface IState {
isRoomEncrypted: boolean;
e2eStatus: string;
e2eStatus: E2EState;
}
export default class MemberTile extends React.Component<IProps, IState> {
@ -51,7 +52,7 @@ export default class MemberTile extends React.Component<IProps, IState> {
showPresence: true,
};
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {
@ -121,7 +122,7 @@ export default class MemberTile extends React.Component<IProps, IState> {
const userTrust = cli.checkUserTrust(userId);
if (!userTrust.isCrossSigningVerified()) {
this.setState({
e2eStatus: userTrust.wasCrossSigningVerified() ? "warning" : "normal",
e2eStatus: userTrust.wasCrossSigningVerified() ? E2EState.Warning : E2EState.Normal,
});
return;
}
@ -138,7 +139,7 @@ export default class MemberTile extends React.Component<IProps, IState> {
return isMe ? !deviceTrust.isCrossSigningVerified() : !deviceTrust.isVerified();
});
this.setState({
e2eStatus: anyDeviceUnverified ? "warning" : "verified",
e2eStatus: anyDeviceUnverified ? E2EState.Warning : E2EState.Verified,
});
}
@ -186,7 +187,7 @@ export default class MemberTile extends React.Component<IProps, IState> {
public render(): JSX.Element {
const member = this.props.member;
const name = this.getDisplayName();
const presenceState = member.user ? member.user.presence : null;
const presenceState = member.user?.presence ?? null;
const av = <MemberAvatar member={member} width={36} height={36} aria-hidden="true" />;
@ -211,7 +212,7 @@ export default class MemberTile extends React.Component<IProps, IState> {
const powerStatus = powerStatusMap.get(powerLevel);
let e2eStatus;
let e2eStatus: E2EState | undefined;
if (this.state.isRoomEncrypted) {
e2eStatus = this.state.e2eStatus;
}
@ -221,7 +222,7 @@ export default class MemberTile extends React.Component<IProps, IState> {
return (
<EntityTile
{...this.props}
presenceState={presenceState}
presenceState={presenceState as PresenceState | null}
presenceLastActiveAgo={member.user ? member.user.lastActiveAgo : 0}
presenceLastTs={member.user ? member.user.lastPresenceTs : 0}
presenceCurrentlyActive={member.user ? member.user.currentlyActive : false}

View file

@ -265,7 +265,7 @@ export class MessageComposer extends React.Component<IProps, IState> {
this.voiceRecording = null;
}
private onTombstoneClick = (ev): void => {
private onTombstoneClick = (ev: ButtonEvent): void => {
ev.preventDefault();
const replacementRoomId = this.context.tombstone.getContent()["replacement_room"];
@ -406,7 +406,7 @@ export class MessageComposer extends React.Component<IProps, IState> {
});
};
private onRecordingEndingSoon = ({ secondsLeft }): void => {
private onRecordingEndingSoon = ({ secondsLeft }: { secondsLeft: number }): void => {
this.setState({ recordingTimeLeftSeconds: secondsLeft });
window.setTimeout(() => this.setState({ recordingTimeLeftSeconds: null }), 3000);
};

View file

@ -44,7 +44,7 @@ interface IClickableProps extends IProps, React.InputHTMLAttributes<Element> {
/**
* If specified will return an AccessibleButton instead of a div.
*/
onClick?(ev: React.MouseEvent);
onClick?(ev: React.MouseEvent): void;
}
interface IState {

View file

@ -43,6 +43,7 @@ const AVATAR_SIZE = 24;
export default class PinnedEventTile extends React.Component<IProps> {
public static contextType = MatrixClientContext;
public context!: React.ContextType<typeof MatrixClientContext>;
private onTileClicked = (): void => {
dis.dispatch<ViewRoomPayload>({

View file

@ -35,7 +35,6 @@ interface IProps {
export default class PresenceLabel extends React.Component<IProps> {
public static defaultProps = {
activeAgo: -1,
presenceState: null,
};
// Return duration as a string using appropriate time units

View file

@ -482,8 +482,7 @@ interface IState {
}
export default class RoomHeader extends React.Component<IProps, IState> {
public static defaultProps = {
editing: false,
public static defaultProps: Partial<IProps> = {
inRoom: false,
excludedRightPanelPhaseButtons: [],
showButtons: true,

View file

@ -16,7 +16,7 @@ limitations under the License.
import { EventType, RoomType } from "matrix-js-sdk/src/@types/event";
import { Room } from "matrix-js-sdk/src/models/room";
import React, { ComponentType, createRef, ReactComponentElement, RefObject } from "react";
import React, { ComponentType, createRef, ReactComponentElement, RefObject, SyntheticEvent } from "react";
import { IState as IRovingTabIndexState, RovingTabIndexProvider } from "../../../accessibility/RovingTabIndex";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
@ -102,10 +102,9 @@ interface ITagAesthetics {
defaultHidden: boolean;
}
interface ITagAestheticsMap {
// @ts-ignore - TS wants this to be a string but we know better
[tagId: TagID]: ITagAesthetics;
}
type TagAestheticsMap = Partial<{
[tagId in TagID]: ITagAesthetics;
}>;
const auxButtonContextMenuPosition = (handle: RefObject<HTMLDivElement>): MenuProps => {
const rect = handle.current.getBoundingClientRect();
@ -380,7 +379,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
);
};
const TAG_AESTHETICS: ITagAestheticsMap = {
const TAG_AESTHETICS: TagAestheticsMap = {
[DefaultTagID.Invite]: {
sectionLabel: _td("Invites"),
isInvite: true,
@ -434,7 +433,7 @@ const TAG_AESTHETICS: ITagAestheticsMap = {
};
export default class RoomList extends React.PureComponent<IProps, IState> {
private dispatcherRef;
private dispatcherRef?: string;
private treeRef = createRef<HTMLDivElement>();
private favouriteMessageWatcher: string;
@ -573,7 +572,7 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
resizeMethod="crop"
/>
);
const viewRoom = (ev): void => {
const viewRoom = (ev: SyntheticEvent): void => {
defaultDispatcher.dispatch<ViewRoomPayload>({
action: Action.ViewRoom,
room_alias: room.canonical_alias || room.aliases?.[0],

View file

@ -104,7 +104,7 @@ export default class RoomPreviewBar extends React.Component<IProps, IState> {
onJoinClick() {},
};
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {
@ -116,7 +116,7 @@ export default class RoomPreviewBar extends React.Component<IProps, IState> {
this.checkInvitedEmail();
}
public componentDidUpdate(prevProps, prevState): void {
public componentDidUpdate(prevProps: IProps, prevState: IState): void {
if (this.props.invitedEmail !== prevProps.invitedEmail || this.props.inviterName !== prevProps.inviterName) {
this.checkInvitedEmail();
}
@ -474,7 +474,7 @@ export default class RoomPreviewBar extends React.Component<IProps, IState> {
const avatar = <RoomAvatar room={this.props.room} oobData={this.props.oobData} />;
const inviteMember = this.getInviteMember();
let inviterElement;
let inviterElement: JSX.Element;
if (inviteMember) {
inviterElement = (
<span>

View file

@ -37,7 +37,7 @@ export default class RoomUpgradeWarningBar extends React.PureComponent<IProps, I
public static contextType = MatrixClientContext;
public context!: React.ContextType<typeof MatrixClientContext>;
public constructor(props, context) {
public constructor(props: IProps, context: React.ContextType<typeof MatrixClientContext>) {
super(props, context);
const tombstone = this.props.room.currentState.getStateEvents("m.room.tombstone", "");

View file

@ -48,7 +48,7 @@ export default class SearchResultTile extends React.Component<IProps> {
// A map of <callId, LegacyCallEventGrouper>
private callEventGroupers = new Map<string, LegacyCallEventGrouper>();
public constructor(props, context) {
public constructor(props: IProps, context: React.ContextType<typeof RoomContext>) {
super(props, context);
this.buildLegacyCallEventGroupers(this.props.timeline);

View file

@ -306,7 +306,8 @@ export class SendMessageComposer extends React.Component<ISendMessageComposerPro
// if we have already sent this reaction, don't redact but don't re-send
if (messageReactions) {
const myReactionEvents = messageReactions.getAnnotationsBySender()[userId] || [];
const myReactionEvents =
messageReactions.getAnnotationsBySender()[userId] || new Set<MatrixEvent>();
const myReactionKeys = [...myReactionEvents]
.filter((event) => !event.isRedacted())
.map((event) => event.getRelation().key);
@ -490,7 +491,7 @@ export class SendMessageComposer extends React.Component<ISendMessageComposerPro
if (json) {
try {
const { parts: serializedParts, replyEventId } = JSON.parse(json);
const parts: Part[] = serializedParts.map((p) => partCreator.deserializePart(p));
const parts: Part[] = serializedParts.map((p: SerializedPart) => partCreator.deserializePart(p));
if (replyEventId) {
dis.dispatch({
action: "reply_to_event",

View file

@ -58,11 +58,11 @@ interface IState {
}
export default class Stickerpicker extends React.PureComponent<IProps, IState> {
public static defaultProps = {
public static defaultProps: Partial<IProps> = {
threadId: null,
};
public static currentWidget;
public static currentWidget?: IWidgetEvent;
private dispatcherRef: string;

View file

@ -47,7 +47,7 @@ interface IState {
export default class ThirdPartyMemberInfo extends React.Component<IProps, IState> {
private room: Room;
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.room = MatrixClientPeg.get().getRoom(this.props.event.getRoomId());
@ -85,7 +85,7 @@ export default class ThirdPartyMemberInfo extends React.Component<IProps, IState
const newDisplayName = ev.getContent().display_name;
const isInvited = isValid3pidInvite(ev);
const newState = { invited: isInvited };
const newState = { invited: isInvited } as IState;
if (newDisplayName) newState["displayName"] = newDisplayName;
this.setState(newState);
}

View file

@ -51,7 +51,7 @@ export default class WhoIsTypingTile extends React.Component<IProps, IState> {
whoIsTypingLimit: 3,
};
public state = {
public state: IState = {
usersTyping: WhoIsTyping.usersTypingApartFromMe(this.props.room),
delayedStopTypingTimers: {},
};
@ -61,7 +61,7 @@ export default class WhoIsTypingTile extends React.Component<IProps, IState> {
MatrixClientPeg.get().on(RoomEvent.Timeline, this.onRoomTimeline);
}
public componentDidUpdate(_, prevState): void {
public componentDidUpdate(prevProps: IProps, prevState: IState): void {
const wasVisible = WhoIsTypingTile.isVisible(prevState);
const isVisible = WhoIsTypingTile.isVisible(this.state);
if (this.props.onShown && !wasVisible && isVisible) {