Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🏷️ making some files comply with strict TS #2247

Merged
merged 7 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 8 additions & 11 deletions packages/desktop-client/src/components/UpdateNotification.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// @ts-strict-ignore
import React from 'react';
import { useSelector } from 'react-redux';

Expand All @@ -11,14 +10,6 @@ import { LinkButton } from './common/LinkButton';
import { Text } from './common/Text';
import { View } from './common/View';

function closeNotification(setAppState) {
// Set a flag to never show an update notification again for this session
setAppState({
updateInfo: null,
showUpdateNotification: false,
});
}

export function UpdateNotification() {
const updateInfo = useSelector(state => state.app.updateInfo);
const showUpdateNotification = useSelector(
Expand Down Expand Up @@ -68,7 +59,7 @@ export function UpdateNotification() {
textDecoration: 'underline',
}}
onClick={() =>
window.Actual.openURLInBrowser(
window.Actual?.openURLInBrowser(
'https://actualbudget.org/docs/releases',
)
}
Expand All @@ -80,7 +71,13 @@ export function UpdateNotification() {
type="bare"
aria-label="Close"
style={{ display: 'inline', padding: '1px 7px 2px 7px' }}
onClick={() => closeNotification(setAppState)}
onClick={() => {
// Set a flag to never show an update notification again for this session
setAppState({
updateInfo: null,
showUpdateNotification: false,
});
}}
>
<SvgClose
width={9}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import { View } from '../common/View';
import { Tooltip } from '../tooltips';

type Item = {
export type Item = {

Check warning on line 24 in packages/desktop-client/src/components/autocomplete/Autocomplete.tsx

View workflow job for this annotation

GitHub Actions / lint

exported declaration 'Item' not used within other modules
id?: string;
name: string;
};
Expand Down Expand Up @@ -691,26 +691,28 @@

type AutocompleteFooterProps = {
show?: boolean;
embedded: boolean;
embedded?: boolean;
children: ReactNode;
};
export function AutocompleteFooter({
show = true,
embedded,
children,
}: AutocompleteFooterProps) {
if (!show) {
return null;
}

return (
show && (
<View
style={{
flexShrink: 0,
...(embedded ? { paddingTop: 5 } : { padding: 5 }),
}}
onMouseDown={e => e.preventDefault()}
>
{children}
</View>
)
<View
style={{
flexShrink: 0,
...(embedded ? { paddingTop: 5 } : { padding: 5 }),
}}
onMouseDown={e => e.preventDefault()}
>
{children}
</View>
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// @ts-strict-ignore
import React, {
type ComponentProps,
Fragment,
Expand All @@ -25,9 +24,11 @@

export type CategoryListProps = {
items: Array<CategoryEntity & { group?: CategoryGroupEntity }>;
getItemProps?: (arg: { item }) => Partial<ComponentProps<typeof View>>;
getItemProps?: (arg: {
item: CategoryEntity;
}) => Partial<ComponentProps<typeof View>>;
highlightedIndex: number;
embedded: boolean;
embedded?: boolean;
footer?: ReactNode;
renderSplitTransactionButton?: (
props: SplitTransactionButtonProps,
Expand All @@ -47,7 +48,7 @@
renderCategoryItemGroupHeader = defaultRenderCategoryItemGroupHeader,
renderCategoryItem = defaultRenderCategoryItem,
}: CategoryListProps) {
let lastGroup = null;
let lastGroup: string | undefined | null = null;

return (
<View>
Expand All @@ -72,10 +73,10 @@
lastGroup = item.cat_group;
return (
<Fragment key={item.id}>
{showGroup && (
<Fragment key={item.group?.name}>
{showGroup && item.group?.name && (
<Fragment key={item.group.name}>
{renderCategoryItemGroupHeader({
title: item.group?.name,
title: item.group.name,
})}
</Fragment>
)}
Expand Down Expand Up @@ -125,7 +126,7 @@
categoryGroups.reduce(
(list, group) =>
list.concat(
group.categories
(group.categories || [])
.filter(category => category.cat_group === group.id)
.map(category => ({
...category,
Expand Down Expand Up @@ -214,8 +215,7 @@
style?: CSSProperties;
};

// eslint-disable-next-line import/no-unused-modules
export function SplitTransactionButton({

Check warning on line 218 in packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx

View workflow job for this annotation

GitHub Actions / lint

exported declaration 'SplitTransactionButton' not used within other modules
Icon,
highlighted,
embedded,
Expand Down
10 changes: 6 additions & 4 deletions packages/loot-core/src/server/db/sort.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// @ts-strict-ignore
export const SORT_INCREMENT = 16384;

function midpoint(items, to) {
function midpoint<T extends { sort_order: number }>(items: T[], to: number) {
const below = items[to - 1];
const above = items[to];

Expand All @@ -14,11 +13,14 @@ function midpoint(items, to) {
}
}

export function shoveSortOrders(items, targetId?: string) {
export function shoveSortOrders<T extends { id: string; sort_order: number }>(
items: T[],
targetId?: string,
) {
const to = items.findIndex(item => item.id === targetId);
const target = items[to];
const before = items[to - 1];
const updates = [];
const updates: Array<{ id: string; sort_order: number }> = [];

// If no target is specified, append at the end
if (!targetId || to === -1) {
Expand Down
27 changes: 13 additions & 14 deletions packages/loot-core/src/server/errors.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
// @ts-strict-ignore
// TODO: normalize error types
export class PostError extends Error {
meta;
reason;
type;
meta: any;

Check warning on line 3 in packages/loot-core/src/server/errors.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
reason: string;
type: 'PostError';

constructor(reason, meta?) {
constructor(reason: string, meta?: any) {

Check warning on line 7 in packages/loot-core/src/server/errors.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
super('PostError: ' + reason);
this.type = 'PostError';
this.reason = reason;
Expand All @@ -14,21 +13,21 @@
}

export class HTTPError extends Error {
statusCode;
responseBody;
statusCode: number;
responseBody: string;

constructor(code, body) {
constructor(code: number, body: string) {
super(`HTTPError: unsuccessful status code (${code}): ${body}`);
this.statusCode = code;
this.responseBody = body;
}
}

export class SyncError extends Error {
meta;
reason;
meta: any;

Check warning on line 27 in packages/loot-core/src/server/errors.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
reason: string;

constructor(reason, meta?) {
constructor(reason: string, meta?: any) {

Check warning on line 30 in packages/loot-core/src/server/errors.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
super('SyncError: ' + reason);
this.reason = reason;
this.meta = meta;
Expand All @@ -46,14 +45,14 @@
}
}

export function APIError(msg, meta?) {
export function APIError(msg: string, meta?: any) {

Check warning on line 48 in packages/loot-core/src/server/errors.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
return { type: 'APIError', message: msg, meta };
}

export function FileDownloadError(reason, meta?) {
export function FileDownloadError(reason: string, meta?: any) {

Check warning on line 52 in packages/loot-core/src/server/errors.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
return { type: 'FileDownloadError', reason, meta };
}

export function FileUploadError(reason, meta?) {
export function FileUploadError(reason: string, meta?: any) {

Check warning on line 56 in packages/loot-core/src/server/errors.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
return { type: 'FileUploadError', reason, meta };
}
104 changes: 24 additions & 80 deletions packages/loot-core/src/server/models.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,38 @@
// @ts-strict-ignore
export function requiredFields(name, row, fields, update) {
import {
AccountEntity,
CategoryEntity,
CategoryGroupEntity,
PayeeEntity,
} from '../types/models';

export function requiredFields<T extends object, K extends keyof T>(
name: string,
row: T,
fields: K[],
update?: boolean,
) {
fields.forEach(field => {
if (update) {
if (row.hasOwnProperty(field) && row[field] == null) {
throw new Error(`${name} is missing field ${field}`);
throw new Error(`${name} is missing field ${String(field)}`);
}
} else {
if (!row.hasOwnProperty(field) || row[field] == null) {
throw new Error(`${name} is missing field ${field}`);
throw new Error(`${name} is missing field ${String(field)}`);
}
}
});
}

export function toDateRepr(str) {
export function toDateRepr(str: string) {
if (typeof str !== 'string') {
throw new Error('toDateRepr not passed a string: ' + str);
}

return parseInt(str.replace(/-/g, ''));
}

export function fromDateRepr(number) {
export function fromDateRepr(number: number) {
if (typeof number !== 'number') {
throw new Error('fromDateRepr not passed a number: ' + number);
}
Expand All @@ -37,7 +48,7 @@ export function fromDateRepr(number) {
}

export const accountModel = {
validate(account, { update }: { update?: boolean } = {}) {
validate(account: AccountEntity, { update }: { update?: boolean } = {}) {
requiredFields(
'account',
account,
Expand All @@ -50,7 +61,7 @@ export const accountModel = {
};

export const categoryModel = {
validate(category, { update }: { update?: boolean } = {}) {
validate(category: CategoryEntity, { update }: { update?: boolean } = {}) {
requiredFields(
'category',
category,
Expand All @@ -64,7 +75,10 @@ export const categoryModel = {
};

export const categoryGroupModel = {
validate(categoryGroup, { update }: { update?: boolean } = {}) {
validate(
categoryGroup: CategoryGroupEntity,
{ update }: { update?: boolean } = {},
) {
requiredFields(
'categoryGroup',
categoryGroup,
Expand All @@ -78,78 +92,8 @@ export const categoryGroupModel = {
};

export const payeeModel = {
validate(payee, { update }: { update?: boolean } = {}) {
validate(payee: PayeeEntity, { update }: { update?: boolean } = {}) {
requiredFields('payee', payee, ['name'], update);
return payee;
},
};

export const transactionModel = {
validate(trans, { update }: { update?: boolean } = {}) {
Copy link
Member Author

Choose a reason for hiding this comment

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

Unused

requiredFields('transaction', trans, ['date', 'acct'], update);

if ('date' in trans) {
// Make sure it's the right format, and also do a sanity check.
// Really old dates can mess up the system and can happen by
// accident
if (
trans.date.match(/^\d{4}-\d{2}-\d{2}$/) == null ||
trans.date < '2000-01-01'
) {
throw new Error('Invalid transaction date: ' + trans.date);
}
}

return trans;
},

toJS(row) {
// Check a non-important field that typically wouldn't be passed in
// manually, and use it as a smoke test to see if this is a
// fully-formed transaction or not.
if (!('location' in row)) {
throw new Error(
'A full transaction is required to be passed to `toJS`. Instead got: ' +
JSON.stringify(row),
);
}

const trans = { ...row };
trans.error = row.error ? JSON.parse(row.error) : null;
trans.isParent = row.isParent === 1 ? true : false;
trans.isChild = row.isChild === 1 ? true : false;
trans.starting_balance_flag =
row.starting_balance_flag === 1 ? true : false;
trans.cleared = row.cleared === 1 ? true : false;
trans.pending = row.pending === 1 ? true : false;
trans.date = trans.date && fromDateRepr(trans.date);
return trans;
},

fromJS(trans) {
const row = { ...trans };
if ('error' in row) {
row.error = trans.error ? JSON.stringify(trans.error) : null;
}
if ('isParent' in row) {
row.isParent = trans.isParent ? 1 : 0;
}
if ('isChild' in row) {
row.isChild = trans.isChild ? 1 : 0;
}
if ('cleared' in row) {
row.cleared = trans.cleared ? 1 : 0;
}
if ('pending' in row) {
row.pending = trans.pending ? 1 : 0;
}
if ('starting_balance_flag' in row) {
row.starting_balance_flag = trans.starting_balance_flag ? 1 : 0;
}
if ('date' in row) {
row.date = toDateRepr(trans.date);
}

return row;
},
};
Loading
Loading