remove most uses of as any in typescript

- replaced many uses of `as any` with another more specific cast `as T`
- filled in missing typed for items that needed to be typed
  - new runtime code was added where necessary to satisfy the new types with comments
- added missing theme variable "sidebar-active" to the Theme variables
- forms using `react-hook-form` are now typechecked
- changed some instances of `target` into `currentTarget` while removing `as any` assertions
This commit is contained in:
bree
2021-07-04 07:09:39 -04:00
parent 504f491074
commit b341f5d166
31 changed files with 161 additions and 117 deletions

View File

@@ -384,7 +384,7 @@ export default function AutoComplete({ detached, state, setState, onClick }: Pic
})
}
onClick={onClick}>
<Emoji emoji={(emojiDictionary as any)[match]} size={20} />
<Emoji emoji={(emojiDictionary as Record<string, string>)[match]} size={20} />
:{match}:
</button>
))}

View File

@@ -1,7 +1,7 @@
import ComboBox from "../ui/ComboBox";
import { connectState } from "../../redux/connector";
import { WithDispatcher } from "../../redux/reducers";
import { LanguageEntry, Languages } from "../../context/Locale";
import { Language, LanguageEntry, Languages } from "../../context/Locale";
type Props = WithDispatcher & {
locale: string;
@@ -15,12 +15,12 @@ export function LocaleSelector(props: Props) {
props.dispatcher &&
props.dispatcher({
type: "SET_LOCALE",
locale: e.currentTarget.value as any
locale: e.currentTarget.value as Language
})
}
>
{Object.keys(Languages).map(x => {
const l = (Languages as any)[x] as LanguageEntry;
const l = Languages[x as keyof typeof Languages];
return (
<option value={x}>
{l.emoji} {l.display}

View File

@@ -15,7 +15,7 @@ export default function UpdateIndicator() {
return internalSubscribe('PWA', 'update', () => setPending(true));
});
if (!pending) return;
if (!pending) return <></>;
const theme = useContext(ThemeContext);
return (

View File

@@ -35,7 +35,12 @@ function Message({ attachContext, message, contrast, content: replacement, head:
const content = message.content as string;
const head = preferHead || (message.replies && message.replies.length > 0);
const userContext = attachContext ? attachContextMenu('Menu', { user: message.author, contextualChannel: message.channel }) : undefined as any; // ! FIXME: tell fatal to make this type generic
// ! FIXME: tell fatal to make this type generic
// bree: Fatal please...
const userContext = attachContext
? attachContextMenu('Menu', { user: message.author, contextualChannel: message.channel }) as any
: undefined;
const openProfile = () => openScreen({ id: 'profile', user_id: message.author });
return (

View File

@@ -18,7 +18,8 @@ export default function AttachmentActions({ attachment }: Props) {
const open_url = `${url}/${filename}`;
const download_url = url.replace('attachments', 'attachments/download')
const filesize = determineFileSize(size as any);
// for some reason revolt.js says the size is a string even though it's a number
const filesize = determineFileSize(size as unknown as number);
switch (metadata.type) {
case 'Image':

View File

@@ -22,13 +22,21 @@ import MarkdownSup from "markdown-it-sup";
// @ts-ignore
import MarkdownSub from "markdown-it-sub";
// TODO: global.d.ts file for defining globals
declare global {
interface Window {
copycode: (element: HTMLDivElement) => void
}
}
// Handler for code block copy.
if (typeof window !== "undefined") {
(window as any).copycode = function(element: HTMLDivElement) {
window.copycode = function(element: HTMLDivElement) {
try {
let code = element.parentElement?.parentElement?.children[1];
if (code) {
navigator.clipboard.writeText((code as any).innerText.trim());
navigator.clipboard.writeText(code.textContent?.trim() ?? '');
}
} catch (e) {}
};
@@ -65,10 +73,17 @@ const defaultRender =
return self.renderToken(tokens, idx, options);
};
// TODO: global.d.ts file for defining globals
declare global {
interface Window {
internalHandleURL: (element: HTMLAnchorElement) => void
}
}
// Handler for internal links, pushes events to React using magic.
if (typeof window !== "undefined") {
(window as any).internalHandleURL = function(element: HTMLAnchorElement) {
const url = new URL(element.href, location as any);
window.internalHandleURL = function(element: HTMLAnchorElement) {
const url = new URL(element.href, location.href);
const pathname = url.pathname;
if (pathname.startsWith("/@")) {
@@ -87,7 +102,7 @@ md.renderer.rules.link_open = function(tokens, idx, options, env, self) {
// For internal links, we should use our own handler to use react-router history.
// @ts-ignore
const href = tokens[idx].attrs[hIndex][1];
const url = new URL(href, location as any);
const url = new URL(href, location.href);
if (url.hostname === location.hostname) {
internal = true;
@@ -161,7 +176,7 @@ export default function Renderer({ content, disallowBigEmoji }: MarkdownProps) {
data-large-emojis={useLargeEmojis}
onClick={ev => {
if (ev.target) {
let element: Element = ev.target as any;
let element = ev.currentTarget;
if (element.classList.contains("spoiler")) {
element.classList.add("shown");
}

View File

@@ -107,11 +107,8 @@ function HomeSidebar(props: Props) {
)}
<Localizer>
<Category
text={
(
<Text id="app.main.categories.conversations" />
) as any
}
text={<Text id="app.main.categories.conversations" />}
/** @ts-ignore : ignored due to conflicting naming between the Category property name and the existing JSX attribute */
action={() => openScreen({ id: "special_input", type: "create_group" })}
/>
</Localizer>

View File

@@ -55,12 +55,8 @@ export function GroupMemberSidebar({ channel, ctx }: Props & { channel: Channels
members.sort((a, b) => {
// ! FIXME: should probably rewrite all this code
let l = ((a.online &&
a.status?.presence !== Users.Presence.Invisible) ??
false) as any | 0;
let r = ((b.online &&
b.status?.presence !== Users.Presence.Invisible) ??
false) as any | 0;
let l = +((a.online && a.status?.presence !== Users.Presence.Invisible) ?? false) | 0;
let r = +((b.online && b.status?.presence !== Users.Presence.Invisible) ?? false) | 0;
let n = r - l;
if (n !== 0) {
@@ -159,12 +155,8 @@ export function ServerMemberSidebar({ channel, ctx }: Props & { channel: Channel
// copy paste from above
users.sort((a, b) => {
// ! FIXME: should probably rewrite all this code
let l = ((a.online &&
a.status?.presence !== Users.Presence.Invisible) ??
false) as any | 0;
let r = ((b.online &&
b.status?.presence !== Users.Presence.Invisible) ??
false) as any | 0;
let l = +((a.online && a.status?.presence !== Users.Presence.Invisible) ?? false) | 0;
let r = +((b.online && b.status?.presence !== Users.Presence.Invisible) ?? false) | 0;
let n = r - l;
if (n !== 0) {

View File

@@ -33,6 +33,7 @@ const CategoryBase = styled.div<Pick<Props, 'variant'>>`
type Props = Omit<JSX.HTMLAttributes<HTMLDivElement>, 'children' | 'as'> & {
text: Children;
// TODO: rename from action to prevent type conflicts with the dom
action?: () => void;
variant?: 'default' | 'uniform';
}