From 2940a3ff4d0f53c7b9680e52dc80927e31626bec Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 24 Mar 2022 14:27:27 -0500 Subject: [PATCH 1/2] Put Typescript in "strict" mode, fix or ignore errors --- app/soapbox/components/account.tsx | 4 +- app/soapbox/components/blurhash.js | 1 + app/soapbox/components/missing_indicator.tsx | 2 +- app/soapbox/components/pull-to-refresh.tsx | 6 +- app/soapbox/components/ui/avatar/avatar.tsx | 4 +- app/soapbox/components/ui/card/card.tsx | 3 +- app/soapbox/components/ui/hstack/hstack.tsx | 6 +- .../components/ui/icon-button/icon-button.tsx | 3 +- app/soapbox/components/ui/input/input.tsx | 3 +- app/soapbox/components/ui/stack/stack.tsx | 6 +- app/soapbox/components/ui/tabs/tabs.tsx | 13 ++++- app/soapbox/components/ui/text/text.tsx | 9 +-- .../features/compose/components/search.tsx | 2 +- .../ui/components/profile-dropdown.tsx | 2 +- app/soapbox/hooks/useOwnAccount.ts | 2 +- app/soapbox/normalizers/account.ts | 20 ++++--- app/soapbox/normalizers/instance.ts | 2 +- app/soapbox/normalizers/poll.ts | 8 ++- app/soapbox/normalizers/status.ts | 34 ++++++----- app/soapbox/reducers/accounts.ts | 7 ++- app/soapbox/reducers/statuses.ts | 57 ++++++++++++------- app/soapbox/types/entities.ts | 47 +++++++++++++++ app/soapbox/types/entities/account.ts | 10 ---- app/soapbox/types/entities/index.ts | 2 - app/soapbox/types/entities/status.ts | 10 ---- app/soapbox/utils/normalizers.js | 7 --- app/soapbox/utils/normalizers.ts | 12 ++++ tsconfig.json | 9 +-- 28 files changed, 177 insertions(+), 114 deletions(-) create mode 100644 app/soapbox/types/entities.ts delete mode 100644 app/soapbox/types/entities/account.ts delete mode 100644 app/soapbox/types/entities/index.ts delete mode 100644 app/soapbox/types/entities/status.ts delete mode 100644 app/soapbox/utils/normalizers.js create mode 100644 app/soapbox/utils/normalizers.ts diff --git a/app/soapbox/components/account.tsx b/app/soapbox/components/account.tsx index cc4efe3fb..a1c428c39 100644 --- a/app/soapbox/components/account.tsx +++ b/app/soapbox/components/account.tsx @@ -54,6 +54,7 @@ const Account = ({ }: IAccount) => { const overflowRef = React.useRef(null); const actionRef = React.useRef(null); + // @ts-ignore const isOnScreen = useOnScreen(overflowRef); const [style, setStyle] = React.useState({ visibility: 'hidden' }); @@ -62,6 +63,7 @@ const Account = ({ const username = useAppSelector((state) => account ? getAcct(account, displayFqn(state)) : null); const handleAction = () => { + // @ts-ignore onActionClick(account); }; @@ -96,7 +98,7 @@ const Account = ({ React.useEffect(() => { if (isOnScreen) { const style: React.CSSProperties = {}; - const actionWidth = actionRef.current?.clientWidth; + const actionWidth = actionRef.current?.clientWidth || 0; if (overflowRef.current) { style.maxWidth = overflowRef.current.clientWidth - 30 - avatarSize - actionWidth; diff --git a/app/soapbox/components/blurhash.js b/app/soapbox/components/blurhash.js index a8f61f066..7a7620699 100644 --- a/app/soapbox/components/blurhash.js +++ b/app/soapbox/components/blurhash.js @@ -46,6 +46,7 @@ function Blurhash({ const ctx = canvas.getContext('2d'); const imageData = new ImageData(pixels, width, height); + // @ts-ignore ctx.putImageData(imageData, 0, 0); } catch (err) { console.error('Blurhash decoding failure', { err, hash }); diff --git a/app/soapbox/components/missing_indicator.tsx b/app/soapbox/components/missing_indicator.tsx index b56abcade..02c383d01 100644 --- a/app/soapbox/components/missing_indicator.tsx +++ b/app/soapbox/components/missing_indicator.tsx @@ -8,7 +8,7 @@ interface MissingIndicatorProps { } const MissingIndicator = ({ nested = false }: MissingIndicatorProps): JSX.Element => ( - + diff --git a/app/soapbox/components/pull-to-refresh.tsx b/app/soapbox/components/pull-to-refresh.tsx index 5c09d155e..fdc8b26cf 100644 --- a/app/soapbox/components/pull-to-refresh.tsx +++ b/app/soapbox/components/pull-to-refresh.tsx @@ -25,9 +25,9 @@ const PullToRefresh = ({ children, onRefresh, ...rest }: IPullToRefresh) => { return ( : null} + pullingContent={<>} + // `undefined` will fallback to the default, while `<>` will render nothing + refreshingContent={onRefresh ? : <>} pullDownThreshold={67} maxPullDownDistance={95} resistance={2} diff --git a/app/soapbox/components/ui/avatar/avatar.tsx b/app/soapbox/components/ui/avatar/avatar.tsx index e2358046a..a327e6840 100644 --- a/app/soapbox/components/ui/avatar/avatar.tsx +++ b/app/soapbox/components/ui/avatar/avatar.tsx @@ -21,9 +21,7 @@ const Avatar = (props: IAvatar) => { return ( = React.forwardRef(({ children, variant, size = 'md' 'space-y-4': true, 'bg-white dark:bg-slate-800 sm:shadow-lg dark:sm:shadow-inset overflow-hidden': variant === 'rounded', [sizes[size]]: true, - [className]: typeof className !== 'undefined', - })} + }, className)} > {children} diff --git a/app/soapbox/components/ui/hstack/hstack.tsx b/app/soapbox/components/ui/hstack/hstack.tsx index d97697670..29dfa9f37 100644 --- a/app/soapbox/components/ui/hstack/hstack.tsx +++ b/app/soapbox/components/ui/hstack/hstack.tsx @@ -39,12 +39,14 @@ const HStack: React.FC = (props) => {
); }; diff --git a/app/soapbox/components/ui/icon-button/icon-button.tsx b/app/soapbox/components/ui/icon-button/icon-button.tsx index 158334346..467c8e4cd 100644 --- a/app/soapbox/components/ui/icon-button/icon-button.tsx +++ b/app/soapbox/components/ui/icon-button/icon-button.tsx @@ -25,8 +25,7 @@ const IconButton = React.forwardRef((props: IIconButton, ref: React.ForwardedRef type='button' className={classNames('flex items-center space-x-2 p-1 rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 dark:ring-offset-0 focus:ring-primary-500', { 'bg-white dark:bg-transparent': !transparent, - [className]: typeof className !== 'undefined', - })} + }, className)} {...filteredProps} > diff --git a/app/soapbox/components/ui/input/input.tsx b/app/soapbox/components/ui/input/input.tsx index fe32b6646..e0be25d49 100644 --- a/app/soapbox/components/ui/input/input.tsx +++ b/app/soapbox/components/ui/input/input.tsx @@ -54,8 +54,7 @@ const Input = React.forwardRef( true, 'pr-7': isPassword, 'pl-8': typeof icon !== 'undefined', - [className]: typeof className !== 'undefined', - })} + }, className)} /> {isPassword ? ( diff --git a/app/soapbox/components/ui/stack/stack.tsx b/app/soapbox/components/ui/stack/stack.tsx index 709db4e5e..46e29d0f6 100644 --- a/app/soapbox/components/ui/stack/stack.tsx +++ b/app/soapbox/components/ui/stack/stack.tsx @@ -35,11 +35,13 @@ const Stack: React.FC = (props) => {
); }; diff --git a/app/soapbox/components/ui/tabs/tabs.tsx b/app/soapbox/components/ui/tabs/tabs.tsx index ad82f7a7a..030911f55 100644 --- a/app/soapbox/components/ui/tabs/tabs.tsx +++ b/app/soapbox/components/ui/tabs/tabs.tsx @@ -24,13 +24,21 @@ const AnimatedTabs: React.FC = ({ children, ...rest }) => { const ref = React.useRef(); const rect = useRect(ref); + // @ts-ignore const top: number = (activeRect && activeRect.bottom) - (rect && rect.top); + // @ts-ignore const width: number = activeRect && activeRect.width - HORIZONTAL_PADDING * 2; + // @ts-ignore const left: number = (activeRect && activeRect.left) - (rect && rect.left) + HORIZONTAL_PADDING; return ( + // @ts-ignore - +
= ({ index, ...props }) => { // callup to set styles whenever we're active React.useLayoutEffect(() => { if (isSelected) { + // @ts-ignore setActiveRect(rect); } }, [isSelected, rect, setActiveRect]); return ( + // @ts-ignore ); }; @@ -115,6 +125,7 @@ const Tabs = ({ items, activeItem }: ITabs) => { key={name} as='button' role='button' + // @ts-ignore title={title} index={idx} > diff --git a/app/soapbox/components/ui/text/text.tsx b/app/soapbox/components/ui/text/text.tsx index b7815c6a3..c1b8f4c25 100644 --- a/app/soapbox/components/ui/text/text.tsx +++ b/app/soapbox/components/ui/text/text.tsx @@ -83,11 +83,13 @@ const Text: React.FC = React.forwardRef( const Comp: React.ElementType = tag; + const alignmentClass = typeof align === 'string' ? alignments[align] : ''; + return ( = React.forwardRef( [weights[weight]]: true, [trackingSizes[tracking]]: true, [families[family]]: true, - [alignments[align]]: typeof align !== 'undefined', - [className]: typeof className !== 'undefined', - })} + [alignmentClass]: typeof align !== 'undefined', + }, className)} /> ); }, diff --git a/app/soapbox/features/compose/components/search.tsx b/app/soapbox/features/compose/components/search.tsx index 791aa0dbf..695163f3c 100644 --- a/app/soapbox/features/compose/components/search.tsx +++ b/app/soapbox/features/compose/components/search.tsx @@ -90,7 +90,7 @@ const Search = (props: ISearch) => { handleSubmit(); } else if (event.key === 'Escape') { - document.querySelector('.ui').parentElement.focus(); + document.querySelector('.ui')?.parentElement?.focus(); } }; diff --git a/app/soapbox/features/ui/components/profile-dropdown.tsx b/app/soapbox/features/ui/components/profile-dropdown.tsx index 7ff98ea1a..0887afe61 100644 --- a/app/soapbox/features/ui/components/profile-dropdown.tsx +++ b/app/soapbox/features/ui/components/profile-dropdown.tsx @@ -25,7 +25,7 @@ interface IProfileDropdown { } type IMenuItem = { - text: string | React.ReactElement, + text: string | React.ReactElement | null, to?: string, icon?: string, action?: (event: React.MouseEvent) => void diff --git a/app/soapbox/hooks/useOwnAccount.ts b/app/soapbox/hooks/useOwnAccount.ts index 6a5937f0b..ea541dfee 100644 --- a/app/soapbox/hooks/useOwnAccount.ts +++ b/app/soapbox/hooks/useOwnAccount.ts @@ -1,7 +1,7 @@ import { useAppSelector } from 'soapbox/hooks'; import { makeGetAccount } from 'soapbox/selectors'; -import type Account from 'soapbox/types/entities/account'; +import type { Account } from 'soapbox/types/entities'; // FIXME: There is no reason this selector shouldn't be global accross the whole app // FIXME: getAccount() has the wrong type?? diff --git a/app/soapbox/normalizers/account.ts b/app/soapbox/normalizers/account.ts index 41dd1dd0f..333e151a8 100644 --- a/app/soapbox/normalizers/account.ts +++ b/app/soapbox/normalizers/account.ts @@ -17,17 +17,19 @@ import { acctFull } from 'soapbox/utils/accounts'; import { unescapeHTML } from 'soapbox/utils/html'; import { mergeDefined, makeEmojiMap } from 'soapbox/utils/normalizers'; +import type { Emoji, Field, EmbeddedEntity } from 'soapbox/types/entities'; + // https://docs.joinmastodon.org/entities/account/ export const AccountRecord = ImmutableRecord({ acct: '', avatar: '', avatar_static: '', - birthday: undefined, + birthday: undefined as Date | undefined, bot: false, created_at: new Date(), display_name: '', - emojis: ImmutableList(), - fields: ImmutableList(), + emojis: ImmutableList(), + fields: ImmutableList(), followers_count: 0, following_count: 0, fqn: '', @@ -37,10 +39,10 @@ export const AccountRecord = ImmutableRecord({ last_status_at: new Date(), location: '', locked: false, - moved: null, + moved: null as EmbeddedEntity | null, note: '', - pleroma: ImmutableMap(), - source: ImmutableMap(), + pleroma: ImmutableMap(), + source: ImmutableMap(), statuses_count: 0, uri: '', url: '', @@ -52,8 +54,8 @@ export const AccountRecord = ImmutableRecord({ display_name_html: '', note_emojified: '', note_plain: '', - patron: ImmutableMap(), - relationship: ImmutableList(), + patron: ImmutableMap(), + relationship: ImmutableList>(), should_refetch: false, }); @@ -61,7 +63,7 @@ export const AccountRecord = ImmutableRecord({ export const FieldRecord = ImmutableRecord({ name: '', value: '', - verified_at: null, + verified_at: null as Date | null, // Internal fields name_emojified: '', diff --git a/app/soapbox/normalizers/instance.ts b/app/soapbox/normalizers/instance.ts index a33601bf9..047e6a1e4 100644 --- a/app/soapbox/normalizers/instance.ts +++ b/app/soapbox/normalizers/instance.ts @@ -82,7 +82,7 @@ const pleromaToMastodonConfig = (instance: ImmutableMap) => { }; // Get the software's default attachment limit -const getAttachmentLimit = (software: string) => software === PLEROMA ? Infinity : 4; +const getAttachmentLimit = (software: string | null) => software === PLEROMA ? Infinity : 4; // Normalize version const normalizeVersion = (instance: ImmutableMap) => { diff --git a/app/soapbox/normalizers/poll.ts b/app/soapbox/normalizers/poll.ts index 592f9aa65..d2b1bf492 100644 --- a/app/soapbox/normalizers/poll.ts +++ b/app/soapbox/normalizers/poll.ts @@ -15,17 +15,19 @@ import emojify from 'soapbox/features/emoji/emoji'; import { normalizeEmoji } from 'soapbox/normalizers/emoji'; import { makeEmojiMap } from 'soapbox/utils/normalizers'; +import type { Emoji, PollOption } from 'soapbox/types/entities'; + // https://docs.joinmastodon.org/entities/poll/ export const PollRecord = ImmutableRecord({ - emojis: ImmutableList(), + emojis: ImmutableList(), expired: false, expires_at: new Date(), id: '', multiple: false, - options: ImmutableList(), + options: ImmutableList(), voters_count: 0, votes_count: 0, - own_votes: null, + own_votes: null as ImmutableList | null, voted: false, }); diff --git a/app/soapbox/normalizers/status.ts b/app/soapbox/normalizers/status.ts index 21cdb42bd..13b68fdbb 100644 --- a/app/soapbox/normalizers/status.ts +++ b/app/soapbox/normalizers/status.ts @@ -16,38 +16,42 @@ import { normalizeEmoji } from 'soapbox/normalizers/emoji'; import { normalizeMention } from 'soapbox/normalizers/mention'; import { normalizePoll } from 'soapbox/normalizers/poll'; +import type { Account, Attachment, Card, Emoji, Mention, Poll, EmbeddedEntity } from 'soapbox/types/entities'; + +type StatusVisibility = 'public' | 'unlisted' | 'private' | 'direct'; + // https://docs.joinmastodon.org/entities/status/ export const StatusRecord = ImmutableRecord({ - account: null, - application: null, + account: null as EmbeddedEntity, + application: null as ImmutableMap | null, bookmarked: false, - card: null, + card: null as EmbeddedEntity, content: '', created_at: new Date(), - emojis: ImmutableList(), + emojis: ImmutableList(), favourited: false, favourites_count: 0, - in_reply_to_account_id: null, - in_reply_to_id: null, + in_reply_to_account_id: null as string | null, + in_reply_to_id: null as string | null, id: '', - language: null, - media_attachments: ImmutableList(), - mentions: ImmutableList(), + language: null as string | null, + media_attachments: ImmutableList(), + mentions: ImmutableList(), muted: false, pinned: false, - pleroma: ImmutableMap(), - poll: null, - quote: null, - reblog: null, + pleroma: ImmutableMap(), + poll: null as EmbeddedEntity, + quote: null as EmbeddedEntity, + reblog: null as EmbeddedEntity, reblogged: false, reblogs_count: 0, replies_count: 0, sensitive: false, spoiler_text: '', - tags: ImmutableList(), + tags: ImmutableList>(), uri: '', url: '', - visibility: 'public', + visibility: 'public' as StatusVisibility, // Internal fields contentHtml: '', diff --git a/app/soapbox/reducers/accounts.ts b/app/soapbox/reducers/accounts.ts index bb9458cf1..444d7ac97 100644 --- a/app/soapbox/reducers/accounts.ts +++ b/app/soapbox/reducers/accounts.ts @@ -32,6 +32,7 @@ import { import { CHATS_FETCH_SUCCESS, CHATS_EXPAND_SUCCESS, CHAT_FETCH_SUCCESS } from 'soapbox/actions/chats'; import { STREAMING_CHAT_UPDATE } from 'soapbox/actions/streaming'; import { normalizeAccount } from 'soapbox/normalizers/account'; +import { normalizeId } from 'soapbox/utils/normalizers'; import { ACCOUNT_IMPORT, @@ -50,7 +51,7 @@ const initialState: State = ImmutableMap(); const minifyAccount = (account: AccountRecord): AccountRecord => { return account.mergeWith((o, n) => n || o, { - moved: account.getIn(['moved', 'id']), + moved: normalizeId(account.getIn(['moved', 'id'])), }); }; @@ -201,8 +202,8 @@ const importAdminUser = (state: State, adminUser: ImmutableMap): St const importAdminUsers = (state: State, adminUsers: Array>): State => { return state.withMutations((state: State) => { - fromJS(adminUsers).forEach(adminUser => { - importAdminUser(state, ImmutableMap(adminUser)); + adminUsers.forEach(adminUser => { + importAdminUser(state, ImmutableMap(fromJS(adminUser))); }); }); }; diff --git a/app/soapbox/reducers/statuses.ts b/app/soapbox/reducers/statuses.ts index c115a9089..617d0c5f4 100644 --- a/app/soapbox/reducers/statuses.ts +++ b/app/soapbox/reducers/statuses.ts @@ -6,7 +6,7 @@ import emojify from 'soapbox/features/emoji/emoji'; import { normalizeStatus } from 'soapbox/normalizers'; import { simulateEmojiReact, simulateUnEmojiReact } from 'soapbox/utils/emoji_reacts'; import { stripCompatibilityFeatures, unescapeHTML } from 'soapbox/utils/html'; -import { makeEmojiMap } from 'soapbox/utils/normalizers'; +import { makeEmojiMap, normalizeId } from 'soapbox/utils/normalizers'; import { EMOJI_REACT_REQUEST, @@ -42,16 +42,20 @@ type State = ImmutableMap; const minifyStatus = (status: StatusRecord): StatusRecord => { return status.mergeWith((o, n) => n || o, { - account: status.getIn(['account', 'id']), - reblog: status.getIn(['reblog', 'id']), - poll: status.getIn(['poll', 'id']), - quote: status.getIn(['quote', 'id']), + account: normalizeId(status.getIn(['account', 'id'])), + reblog: normalizeId(status.getIn(['reblog', 'id'])), + poll: normalizeId(status.getIn(['poll', 'id'])), + quote: normalizeId(status.getIn(['quote', 'id'])), }); }; // Gets titles of poll options from status -const getPollOptionTitles = (status: StatusRecord): Array => { - return status.poll?.options.map(({ title }: { title: string }) => title); +const getPollOptionTitles = ({ poll }: StatusRecord): ImmutableList => { + if (poll && typeof poll === 'object') { + return poll.options.map(({ title }) => title); + } else { + return ImmutableList(); + } }; // Creates search text from the status @@ -63,14 +67,14 @@ const buildSearchContent = (status: StatusRecord): string => { status.content, ]).concat(pollOptionTitles); - return unescapeHTML(fields.join('\n\n')); + return unescapeHTML(fields.join('\n\n')) || ''; }; // Only calculate these values when status first encountered // Otherwise keep the ones already in the reducer export const calculateStatus = ( status: StatusRecord, - oldStatus: StatusRecord, + oldStatus?: StatusRecord, expandSpoilers: boolean = false, ): StatusRecord => { if (oldStatus) { @@ -86,7 +90,7 @@ export const calculateStatus = ( const emojiMap = makeEmojiMap(status.emojis); return status.merge({ - search_index: domParser.parseFromString(searchContent, 'text/html').documentElement.textContent || undefined, + search_index: domParser.parseFromString(searchContent, 'text/html').documentElement.textContent || '', contentHtml: stripCompatibilityFeatures(emojify(status.content, emojiMap)), spoilerHtml: emojify(escapeTextContentForBrowser(spoilerText), emojiMap), hidden: expandSpoilers ? false : spoilerText.length > 0 || status.sensitive, @@ -100,7 +104,7 @@ const isQuote = (status: StatusRecord) => { }; // Preserve quote if an existing status already has it -const fixQuote = (status: StatusRecord, oldStatus: StatusRecord): StatusRecord => { +const fixQuote = (status: StatusRecord, oldStatus?: StatusRecord): StatusRecord => { if (oldStatus && !status.quote && isQuote(status)) { return status .set('quote', oldStatus.quote) @@ -111,7 +115,7 @@ const fixQuote = (status: StatusRecord, oldStatus: StatusRecord): StatusRecord = }; const fixStatus = (state: State, status: APIEntity, expandSpoilers: boolean): StatusRecord => { - const oldStatus: StatusRecord = state.get(status.id); + const oldStatus = state.get(status.id); return normalizeStatus(status).withMutations(status => { fixQuote(status, oldStatus); @@ -154,6 +158,25 @@ const deletePendingStatus = (state: State, { in_reply_to_id }: APIEntity) => { } }; +/** Simulate favourite/unfavourite of status for optimistic interactions */ +const simulateFavourite = ( + state: State, + statusId: string, + favourited: boolean, +): State => { + const status = state.get(statusId); + if (!status) return state; + + const delta = favourited ? +1 : -1; + + const updatedStatus = status.merge({ + favourited, + favourites_count: Math.max(0, status.favourites_count + delta), + }); + + return state.set(statusId, updatedStatus); +}; + const initialState: State = ImmutableMap(); export default function statuses(state = initialState, action: AnyAction): State { @@ -167,15 +190,9 @@ export default function statuses(state = initialState, action: AnyAction): State case STATUS_CREATE_FAIL: return deletePendingStatus(state, action.params); case FAVOURITE_REQUEST: - return state.update(action.status.get('id'), status => - status - .set('favourited', true) - .update('favourites_count', count => count + 1)); + return simulateFavourite(state, action.status.id, true); case UNFAVOURITE_REQUEST: - return state.update(action.status.get('id'), status => - status - .set('favourited', false) - .update('favourites_count', count => Math.max(0, count - 1))); + return simulateFavourite(state, action.status.id, false); case EMOJI_REACT_REQUEST: return state .updateIn( diff --git a/app/soapbox/types/entities.ts b/app/soapbox/types/entities.ts new file mode 100644 index 000000000..65a5bf057 --- /dev/null +++ b/app/soapbox/types/entities.ts @@ -0,0 +1,47 @@ +import { + AccountRecord, + AttachmentRecord, + CardRecord, + EmojiRecord, + FieldRecord, + InstanceRecord, + MentionRecord, + NotificationRecord, + PollRecord, + PollOptionRecord, + StatusRecord, +} from 'soapbox/normalizers'; + +import type { Record as ImmutableRecord } from 'immutable'; + +type Account = ReturnType; +type Attachment = ReturnType; +type Card = ReturnType; +type Emoji = ReturnType; +type Field = ReturnType; +type Instance = ReturnType; +type Mention = ReturnType; +type Notification = ReturnType; +type Poll = ReturnType; +type PollOption = ReturnType; +type Status = ReturnType; + +// Utility types +type EmbeddedEntity = null | string | ReturnType>; + +export { + Account, + Attachment, + Card, + Emoji, + Field, + Instance, + Mention, + Notification, + Poll, + PollOption, + Status, + + // Utility types + EmbeddedEntity, +}; diff --git a/app/soapbox/types/entities/account.ts b/app/soapbox/types/entities/account.ts deleted file mode 100644 index eeb06dd90..000000000 --- a/app/soapbox/types/entities/account.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Account entity. - * https://docs.joinmastodon.org/entities/account/ - **/ - -import { AccountRecord } from 'soapbox/normalizers'; - -type Account = ReturnType - -export default Account; diff --git a/app/soapbox/types/entities/index.ts b/app/soapbox/types/entities/index.ts deleted file mode 100644 index 2bfc0daf8..000000000 --- a/app/soapbox/types/entities/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as Account } from './account'; -export { default as Status } from './status'; diff --git a/app/soapbox/types/entities/status.ts b/app/soapbox/types/entities/status.ts deleted file mode 100644 index 3c7f66c8b..000000000 --- a/app/soapbox/types/entities/status.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Status entity. - * https://docs.joinmastodon.org/entities/status/ - **/ - -import { StatusRecord } from 'soapbox/normalizers'; - -type Status = ReturnType - -export default Status; diff --git a/app/soapbox/utils/normalizers.js b/app/soapbox/utils/normalizers.js deleted file mode 100644 index d16b2a07c..000000000 --- a/app/soapbox/utils/normalizers.js +++ /dev/null @@ -1,7 +0,0 @@ -// Use new value only if old value is undefined -export const mergeDefined = (oldVal, newVal) => oldVal === undefined ? newVal : oldVal; - -export const makeEmojiMap = emojis => emojis.reduce((obj, emoji) => { - obj[`:${emoji.shortcode}:`] = emoji; - return obj; -}, {}); diff --git a/app/soapbox/utils/normalizers.ts b/app/soapbox/utils/normalizers.ts new file mode 100644 index 000000000..a74ca582d --- /dev/null +++ b/app/soapbox/utils/normalizers.ts @@ -0,0 +1,12 @@ +// Use new value only if old value is undefined +export const mergeDefined = (oldVal: any, newVal: any) => oldVal === undefined ? newVal : oldVal; + +export const makeEmojiMap = (emojis: any) => emojis.reduce((obj: any, emoji: any) => { + obj[`:${emoji.shortcode}:`] = emoji; + return obj; +}, {}); + +/** Normalize entity ID */ +export const normalizeId = (id: any): string | null => { + return typeof id === 'string' ? id : null; +}; diff --git a/tsconfig.json b/tsconfig.json index 8412a8997..6af5fd813 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,14 +2,7 @@ "compilerOptions": { "baseUrl": "app/", "sourceMap": true, - "alwaysStrict": true, - "strictNullChecks": false, - "strictBindCallApply": true, - "strictFunctionTypes": true, - "strictPropertyInitialization": false, - "noImplicitAny": true, - "noImplicitThis": true, - "useUnknownInCatchVariables": true, + "strict": true, "module": "es6", "target": "es5", "jsx": "react", From f8592b36169d3febb88ff01946d2ba05f04b89c7 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 24 Mar 2022 14:44:39 -0500 Subject: [PATCH 2/2] Jest: fix tests --- .../__snapshots__/timeline_queue_button_header-test.js.snap | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/soapbox/components/__tests__/__snapshots__/timeline_queue_button_header-test.js.snap b/app/soapbox/components/__tests__/__snapshots__/timeline_queue_button_header-test.js.snap index 7669b4fd3..21f128b39 100644 --- a/app/soapbox/components/__tests__/__snapshots__/timeline_queue_button_header-test.js.snap +++ b/app/soapbox/components/__tests__/__snapshots__/timeline_queue_button_header-test.js.snap @@ -44,7 +44,6 @@ exports[` renders correctly 2`] = `

Click to see 1 new post

@@ -73,7 +72,6 @@ exports[` renders correctly 3`] = `

Click to see 9999999 new posts