Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Improve typescript null checking in places (#10073 (#10073
Browse files Browse the repository at this point in the history
* Improve typescript null checking in places

* Iterate

* Fix Timer.ts
  • Loading branch information
t3chguy authored Feb 3, 2023
1 parent 97506cb commit 9743852
Show file tree
Hide file tree
Showing 43 changed files with 155 additions and 154 deletions.
6 changes: 3 additions & 3 deletions src/Avatar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function avatarUrlForMember(
height: number,
resizeMethod: ResizeMethod,
): string {
let url: string;
let url: string | null | undefined;
if (member?.getMxcAvatarUrl()) {
url = mediaFromMxc(member.getMxcAvatarUrl()).getThumbnailOfSourceHttp(width, height, resizeMethod);
}
Expand Down Expand Up @@ -118,7 +118,7 @@ export function defaultAvatarUrlForString(s: string): string {
* @param {string} name
* @return {string} the first letter
*/
export function getInitialLetter(name: string): string {
export function getInitialLetter(name: string): string | undefined {
if (!name) {
// XXX: We should find out what causes the name to sometimes be falsy.
console.trace("`name` argument to `getInitialLetter` not supplied");
Expand Down Expand Up @@ -146,7 +146,7 @@ export function avatarUrlForRoom(
if (!room) return null; // null-guard

if (room.getMxcAvatarUrl()) {
return mediaFromMxc(room.getMxcAvatarUrl()).getThumbnailOfSourceHttp(width, height, resizeMethod);
return mediaFromMxc(room.getMxcAvatarUrl() || undefined).getThumbnailOfSourceHttp(width, height, resizeMethod);
}

// space rooms cannot be DMs so skip the rest
Expand Down
10 changes: 5 additions & 5 deletions src/BasePlatform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export default abstract class BasePlatform {
if (MatrixClientPeg.userRegisteredWithinLastHours(24)) return false;

try {
const [version, deferUntil] = JSON.parse(localStorage.getItem(UPDATE_DEFER_KEY));
const [version, deferUntil] = JSON.parse(localStorage.getItem(UPDATE_DEFER_KEY)!);
return newVersion !== version || Date.now() > deferUntil;
} catch (e) {
return true;
Expand Down Expand Up @@ -211,7 +211,7 @@ export default abstract class BasePlatform {
metricsTrigger: "Notification",
};

if (ev.getThread()) {
if (ev?.getThread()) {
payload.event_id = ev.getId();
}

Expand Down Expand Up @@ -255,7 +255,7 @@ export default abstract class BasePlatform {
return false;
}

public getSettingValue(settingName: string): Promise<any> {
public async getSettingValue(settingName: string): Promise<any> {
return undefined;
}

Expand All @@ -278,7 +278,7 @@ export default abstract class BasePlatform {
public setSpellCheckEnabled(enabled: boolean): void {}

public async getSpellCheckEnabled(): Promise<boolean> {
return null;
return false;
}

public setSpellCheckLanguages(preferredLangs: string[]): void {}
Expand Down Expand Up @@ -333,7 +333,7 @@ export default abstract class BasePlatform {
// persist hs url and is url for when the user is returned to the app with the login token
localStorage.setItem(SSO_HOMESERVER_URL_KEY, mxClient.getHomeserverUrl());
if (mxClient.getIdentityServerUrl()) {
localStorage.setItem(SSO_ID_SERVER_URL_KEY, mxClient.getIdentityServerUrl());
localStorage.setItem(SSO_ID_SERVER_URL_KEY, mxClient.getIdentityServerUrl()!);
}
if (idpId) {
localStorage.setItem(SSO_IDP_ID_KEY, idpId);
Expand Down
2 changes: 1 addition & 1 deletion src/ContentMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ export default class ContentMessages {
const replyToEvent = SdkContextClass.instance.roomViewStore.getQuotingEvent();
if (!this.mediaConfig) {
// hot-path optimization to not flash a spinner if we don't need to
const modal = Modal.createDialog(Spinner, null, "mx_Dialog_spinner");
const modal = Modal.createDialog(Spinner, undefined, "mx_Dialog_spinner");
await this.ensureMediaConfigFetched(matrixClient);
modal.close();
}
Expand Down
4 changes: 2 additions & 2 deletions src/DecryptionFailureTracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ export class DecryptionFailureTracker {
public trackedEvents: Set<string> = new Set();

// Set to an interval ID when `start` is called
public checkInterval: number = null;
public trackInterval: number = null;
public checkInterval: number | null = null;
public trackInterval: number | null = null;

// Spread the load on `Analytics` by tracking at a low frequency, `TRACK_INTERVAL_MS`.
public static TRACK_INTERVAL_MS = 60000;
Expand Down
6 changes: 3 additions & 3 deletions src/DeviceListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ export default class DeviceListener {
private dismissedThisDeviceToast = false;
// cache of the key backup info
private keyBackupInfo: IKeyBackupInfo | null = null;
private keyBackupFetchedAt: number = null;
private keyBackupFetchedAt: number | null = null;
private keyBackupStatusChecked = false;
// We keep a list of our own device IDs so we can batch ones that were already
// there the last time the app launched into a single toast, but display new
// ones in their own toasts.
private ourDeviceIdsAtStart: Set<string> = null;
private ourDeviceIdsAtStart: Set<string> | null = null;
// The set of device IDs we're currently displaying toasts for
private displayingToastsForDeviceIds = new Set<string>();
private running = false;
Expand Down Expand Up @@ -203,7 +203,7 @@ export default class DeviceListener {
}
};

private onSync = (state: SyncState, prevState?: SyncState): void => {
private onSync = (state: SyncState, prevState: SyncState | null): void => {
if (state === "PREPARED" && prevState === null) {
this.recheck();
}
Expand Down
7 changes: 6 additions & 1 deletion src/ImageUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ limitations under the License.
* consume in the timeline, when performing scroll offset calculations
* (e.g. scroll locking)
*/
export function thumbHeight(fullWidth: number, fullHeight: number, thumbWidth: number, thumbHeight: number): number {
export function thumbHeight(
fullWidth: number,
fullHeight: number,
thumbWidth: number,
thumbHeight: number,
): number | null {
if (!fullWidth || !fullHeight) {
// Cannot calculate thumbnail height for image: missing w/h in metadata. We can't even
// log this because it's spammy
Expand Down
8 changes: 4 additions & 4 deletions src/accessibility/KeyboardShortcutUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ const getUIOnlyShortcuts = (): IKeyboardShortcuts => {
},
};

if (PlatformPeg.get().overrideBrowserShortcuts()) {
if (PlatformPeg.get()?.overrideBrowserShortcuts()) {
// XXX: This keyboard shortcut isn't manually added to
// KeyBindingDefaults as it can't be easily handled by the
// KeyBindingManager
Expand All @@ -92,7 +92,7 @@ const getUIOnlyShortcuts = (): IKeyboardShortcuts => {
* This function gets keyboard shortcuts that can be consumed by the KeyBindingDefaults.
*/
export const getKeyboardShortcuts = (): IKeyboardShortcuts => {
const overrideBrowserShortcuts = PlatformPeg.get().overrideBrowserShortcuts();
const overrideBrowserShortcuts = PlatformPeg.get()?.overrideBrowserShortcuts();

return Object.keys(KEYBOARD_SHORTCUTS)
.filter((k: KeyBindingAction) => {
Expand Down Expand Up @@ -120,11 +120,11 @@ export const getKeyboardShortcutsForUI = (): IKeyboardShortcuts => {
}, {} as IKeyboardShortcuts);
};

export const getKeyboardShortcutValue = (name: string): KeyCombo => {
export const getKeyboardShortcutValue = (name: string): KeyCombo | undefined => {
return getKeyboardShortcutsForUI()[name]?.default;
};

export const getKeyboardShortcutDisplayName = (name: string): string | null => {
export const getKeyboardShortcutDisplayName = (name: string): string | undefined => {
const keyboardShortcutDisplayName = getKeyboardShortcutsForUI()[name]?.displayName;
return keyboardShortcutDisplayName && _t(keyboardShortcutDisplayName);
};
16 changes: 7 additions & 9 deletions src/accessibility/RovingTabIndex.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function checkInputableElement(el: HTMLElement): boolean {
}

export interface IState {
activeRef: Ref;
activeRef?: Ref;
refs: Ref[];
}

Expand All @@ -67,7 +67,6 @@ interface IContext {

export const RovingTabIndexContext = createContext<IContext>({
state: {
activeRef: null,
refs: [], // list of refs in DOM order
},
dispatch: () => {},
Expand Down Expand Up @@ -102,7 +101,7 @@ export const reducer: Reducer<IState, IAction> = (state: IState, action: IAction
return 0;
}

const position = a.current.compareDocumentPosition(b.current);
const position = a.current!.compareDocumentPosition(b.current!);

if (position & Node.DOCUMENT_POSITION_FOLLOWING || position & Node.DOCUMENT_POSITION_CONTAINED_BY) {
return -1;
Expand Down Expand Up @@ -167,7 +166,7 @@ export const findSiblingElement = (
refs: RefObject<HTMLElement>[],
startIndex: number,
backwards = false,
): RefObject<HTMLElement> => {
): RefObject<HTMLElement> | undefined => {
if (backwards) {
for (let i = startIndex; i < refs.length && i >= 0; i--) {
if (refs[i].current?.offsetParent !== null) {
Expand All @@ -191,7 +190,6 @@ export const RovingTabIndexProvider: React.FC<IProps> = ({
onKeyDown,
}) => {
const [state, dispatch] = useReducer<Reducer<IState, IAction>>(reducer, {
activeRef: null,
refs: [],
});

Expand All @@ -208,15 +206,15 @@ export const RovingTabIndexProvider: React.FC<IProps> = ({

let handled = false;
const action = getKeyBindingsManager().getAccessibilityAction(ev);
let focusRef: RefObject<HTMLElement>;
let focusRef: RefObject<HTMLElement> | undefined;
// Don't interfere with input default keydown behaviour
// but allow people to move focus from it with Tab.
if (checkInputableElement(ev.target as HTMLElement)) {
switch (action) {
case KeyBindingAction.Tab:
handled = true;
if (context.state.refs.length > 0) {
const idx = context.state.refs.indexOf(context.state.activeRef);
const idx = context.state.refs.indexOf(context.state.activeRef!);
focusRef = findSiblingElement(
context.state.refs,
idx + (ev.shiftKey ? -1 : 1),
Expand Down Expand Up @@ -252,7 +250,7 @@ export const RovingTabIndexProvider: React.FC<IProps> = ({
) {
handled = true;
if (context.state.refs.length > 0) {
const idx = context.state.refs.indexOf(context.state.activeRef);
const idx = context.state.refs.indexOf(context.state.activeRef!);
focusRef = findSiblingElement(context.state.refs, idx + 1);
}
}
Expand All @@ -266,7 +264,7 @@ export const RovingTabIndexProvider: React.FC<IProps> = ({
) {
handled = true;
if (context.state.refs.length > 0) {
const idx = context.state.refs.indexOf(context.state.activeRef);
const idx = context.state.refs.indexOf(context.state.activeRef!);
focusRef = findSiblingElement(context.state.refs, idx - 1, true);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/actions/MatrixActionCreators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ function createRoomTimelineAction(
action: "MatrixActions.Room.timeline",
event: timelineEvent,
isLiveEvent: data.liveEvent,
isLiveUnfilteredRoomTimelineEvent: room && data.timeline.getTimelineSet() === room.getUnfilteredTimelineSet(),
isLiveUnfilteredRoomTimelineEvent: data.timeline.getTimelineSet() === room?.getUnfilteredTimelineSet(),
room,
};
}
Expand Down
6 changes: 3 additions & 3 deletions src/audio/PlaybackQueue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export class PlaybackQueue {
private playbacks = new Map<string, Playback>(); // keyed by event ID
private clockStates = new Map<string, number>(); // keyed by event ID
private playbackIdOrder: string[] = []; // event IDs, last == current
private currentPlaybackId: string; // event ID, broken out from above for ease of use
private currentPlaybackId: string | null = null; // event ID, broken out from above for ease of use
private recentFullPlays = new Set<string>(); // event IDs

public constructor(private room: Room) {
Expand All @@ -68,7 +68,7 @@ export class PlaybackQueue {
const room = cli.getRoom(roomId);
if (!room) throw new Error("Unknown room");
if (PlaybackQueue.queues.has(room.roomId)) {
return PlaybackQueue.queues.get(room.roomId);
return PlaybackQueue.queues.get(room.roomId)!;
}
const queue = new PlaybackQueue(room);
PlaybackQueue.queues.set(room.roomId, queue);
Expand Down Expand Up @@ -101,7 +101,7 @@ export class PlaybackQueue {
const wasLastPlaying = this.currentPlaybackId === mxEvent.getId();
if (newState === PlaybackState.Stopped && this.clockStates.has(mxEvent.getId()) && !wasLastPlaying) {
// noinspection JSIgnoredPromiseFromCall
playback.skipTo(this.clockStates.get(mxEvent.getId()));
playback.skipTo(this.clockStates.get(mxEvent.getId())!);
} else if (newState === PlaybackState.Stopped) {
// Remove the now-useless clock for some space savings
this.clockStates.delete(mxEvent.getId());
Expand Down
4 changes: 2 additions & 2 deletions src/autocomplete/AutocompleteProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export default abstract class AutocompleteProvider {
* @param {boolean} force True if the user is forcing completion
* @return {object} { command, range } where both objects fields are null if no match
*/
public getCurrentCommand(query: string, selection: ISelectionRange, force = false): ICommand {
public getCurrentCommand(query: string, selection: ISelectionRange, force = false): ICommand | null {
let commandRegex = this.commandRegex;

if (force && this.shouldForceComplete()) {
Expand All @@ -83,7 +83,7 @@ export default abstract class AutocompleteProvider {

commandRegex.lastIndex = 0;

let match: RegExpExecArray;
let match: RegExpExecArray | null;
while ((match = commandRegex.exec(query)) !== null) {
const start = match.index;
const end = start + match[0].length;
Expand Down
4 changes: 2 additions & 2 deletions src/autocomplete/Autocompleter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export default class Autocompleter {
to predict whether an action will actually do what is intended
*/
// list of results from each provider, each being a list of completions or null if it times out
const completionsList: ICompletion[][] = await Promise.all(
const completionsList: Array<ICompletion[] | null> = await Promise.all(
this.providers.map(async (provider): Promise<ICompletion[] | null> => {
return timeout(
provider.getCompletions(query, selection, force, limit),
Expand All @@ -113,6 +113,6 @@ export default class Autocompleter {
command: this.providers[i].getCurrentCommand(query, selection, force),
};
})
.filter(Boolean);
.filter(Boolean) as IProviderCompletions[];
}
}
6 changes: 3 additions & 3 deletions src/autocomplete/CommandProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ export default class CommandProvider extends AutocompleteProvider {
if (command[0] !== command[1]) {
// The input looks like a command with arguments, perform exact match
const name = command[1].slice(1); // strip leading `/`
if (CommandMap.has(name) && CommandMap.get(name).isEnabled()) {
if (CommandMap.has(name) && CommandMap.get(name)!.isEnabled()) {
// some commands, namely `me` don't suit having the usage shown whilst typing their arguments
if (CommandMap.get(name).hideCompletionAfterSpace) return [];
matches = [CommandMap.get(name)];
if (CommandMap.get(name)!.hideCompletionAfterSpace) return [];
matches = [CommandMap.get(name)!];
}
} else {
if (query === "/") {
Expand Down
8 changes: 4 additions & 4 deletions src/autocomplete/RoomProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ function canonicalScore(displayedAlias: string, room: Room): number {

function matcherObject(
room: Room,
displayedAlias: string,
displayedAlias: string | null,
matchName = "",
): {
room: Room;
matchName: string;
displayedAlias: string;
displayedAlias: string | null;
} {
return {
room,
Expand All @@ -58,7 +58,7 @@ export default class RoomProvider extends AutocompleteProvider {

public constructor(room: Room, renderingType?: TimelineRenderingType) {
super({ commandRegex: ROOM_REGEX, renderingType });
this.matcher = new QueryMatcher([], {
this.matcher = new QueryMatcher<ReturnType<typeof matcherObject>>([], {
keys: ["displayedAlias", "matchName"],
});
}
Expand All @@ -79,7 +79,7 @@ export default class RoomProvider extends AutocompleteProvider {
const { command, range } = this.getCurrentCommand(query, selection, force);
if (command) {
// the only reason we need to do this is because Fuse only matches on properties
let matcherObjects = this.getRooms().reduce((aliases, room) => {
let matcherObjects = this.getRooms().reduce<ReturnType<typeof matcherObject>[]>((aliases, room) => {
if (room.getCanonicalAlias()) {
aliases = aliases.concat(matcherObject(room, room.getCanonicalAlias(), room.name));
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/structures/MatrixChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
onFinished: (confirm) => {
if (confirm) {
// FIXME: controller shouldn't be loading a view :(
const modal = Modal.createDialog(Spinner, null, "mx_Dialog_spinner");
const modal = Modal.createDialog(Spinner, undefined, "mx_Dialog_spinner");

MatrixClientPeg.get()
.leave(payload.room_id)
Expand Down
8 changes: 4 additions & 4 deletions src/components/views/messages/MKeyVerificationConclusion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export default class MKeyVerificationConclusion extends React.Component<IProps>
this.forceUpdate();
};

public static shouldRender(mxEvent: MatrixEvent, request: VerificationRequest): boolean {
public static shouldRender(mxEvent: MatrixEvent, request?: VerificationRequest): boolean {
// normally should not happen
if (!request) {
return false;
Expand All @@ -99,9 +99,9 @@ export default class MKeyVerificationConclusion extends React.Component<IProps>
return true;
}

public render(): JSX.Element {
public render(): JSX.Element | null {
const { mxEvent } = this.props;
const request = mxEvent.verificationRequest;
const request = mxEvent.verificationRequest!;

if (!MKeyVerificationConclusion.shouldRender(mxEvent, request)) {
return null;
Expand All @@ -110,7 +110,7 @@ export default class MKeyVerificationConclusion extends React.Component<IProps>
const client = MatrixClientPeg.get();
const myUserId = client.getUserId();

let title;
let title: string | undefined;

if (request.done) {
title = _t("You verified %(name)s", {
Expand Down
Loading

2 comments on commit 9743852

@menturion
Copy link
Contributor

Choose a reason for hiding this comment

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

@t3chguy

Ad src/customisations/Security.ts:

I think that most implementations of getting the secret storage key by calling method getSecretStorageKey would require a promise (same as with getting the dehydration key getDehydrationKey), e.g. by requesting an external key server. Additionally passing the keyInfo would allow to derive the key, if needed:

function getSecretStorageKey(keyInfo: ISecretStorageKeyInfo): Promise<Uint8Array | null> {

}

If so, the call In matrix-react-sdk\src\SecurityManager.ts would be const keyFromCustomisations = await SecurityCustomisations.getSecretStorageKey?.(keyInfo);

@t3chguy
Copy link
Member Author

@t3chguy t3chguy commented on 9743852 Feb 6, 2023

Choose a reason for hiding this comment

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

@menturion I think that is unrelated to the context of this PR which is improving type correctness, not changing functionality.

Please sign in to comment.