Skip to content

Commit

Permalink
♻️ typesafe use of any and object #130
Browse files Browse the repository at this point in the history
  • Loading branch information
trydofor committed Dec 20, 2024
1 parent bc04d02 commit 1d4ca29
Show file tree
Hide file tree
Showing 10 changed files with 43 additions and 48 deletions.
6 changes: 6 additions & 0 deletions .changeset/sharp-dingos-explode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@fessional/razor-common": patch
"@fessional/razor-mobile": patch
---

♻️ SafeAny, SafeObj, TypedFetch status function
6 changes: 2 additions & 4 deletions layers/common/composables/UseApiRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@ export function useApiRoute() {
const prefix = useRuntimeConfig().public.apiRoute;
return {
url: (uri: string) => prefix + uri,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
get: <Data>(uri: string, query?: Record<string, any>) => $fetch<DataResult<Data>>(
get: <Data>(uri: string, query?: SafeObj) => $fetch<DataResult<Data>>(
prefix + uri,
{
method: 'get',
query,
}),
// eslint-disable-next-line @typescript-eslint/no-explicit-any
post: <Data>(uri: string, body?: Record<string, any> | URLSearchParams | FormData, query?: Record<string, any>) => $fetch<DataResult<Data>>(
post: <Data>(uri: string, body?: SafeObj | URLSearchParams | FormData, query?: SafeObj) => $fetch<DataResult<Data>>(
prefix + uri,
{
method: 'post',
Expand Down
18 changes: 6 additions & 12 deletions layers/common/tests/safe-converter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,13 @@ describe('safeConvert', () => {
});

it('should break after one function evaluation if once is true', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const nestedFunction: any = () => () => 10;
const nestedFunction: SafeAny = () => () => 10;
const result = safeConvert(nestedFunction, 'default', value => value > 5 ? 'valid' : null, true);
expect(result).toBe('default');
});

it('should evaluate nested functions until a value is returned when once is false', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const nestedFunction: any = () => () => 10;
const nestedFunction: SafeAny = () => () => 10;
const result = safeConvert(nestedFunction, 'default', value => value > 5 ? 'valid' : null);
expect(result).toBe('valid');
});
Expand Down Expand Up @@ -138,8 +136,7 @@ describe('safeBigint', () => {
expect(safeBigint(null)).toBe(0n);
expect(safeBigint(undefined)).toBe(0n);

// eslint-disable-next-line @typescript-eslint/no-explicit-any
expect(safeBigint({} as any)).toBe(0n);
expect(safeBigint({} as SafeAny)).toBe(0n);
expect(safeBigint(NaN)).toBe(0n);
});

Expand Down Expand Up @@ -203,10 +200,8 @@ describe('safeBoolean', () => {
expect(safeBoolean(undefined, false)).toBe(false);
expect(safeBoolean(NaN, false)).toBe(false);

// eslint-disable-next-line @typescript-eslint/no-explicit-any
expect(safeBoolean({} as any, true)).toBe(true);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
expect(safeBoolean({} as any, false)).toBe(false);
expect(safeBoolean({} as SafeAny, true)).toBe(true);
expect(safeBoolean({} as SafeAny, false)).toBe(false);
});
});

Expand Down Expand Up @@ -439,8 +434,7 @@ describe('numberKey;', () => {
const d3 = 0.1 + 0.2;

it('number key of object', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const obj = { 1: '1', 0.3: '0.3' } as any;
const obj = { 1: '1', 0.3: '0.3' } as SafeAny;
expect(obj[1]).toBe('1');
expect(obj['1']).toBe('1');
expect(obj[d3]).toBe(undefined);
Expand Down
12 changes: 12 additions & 0 deletions layers/common/types/common.global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@
*/
type OrElse<T, D> = NonNullable<T> | D;

/**
* typesafe use of `any` to reduce eslint comments
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type SafeAny = any;

/**
* typesafe use of `object` to reduce eslint comments
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type SafeObj = Record<string, any>;

/**
* short string value of true or false
*/
Expand Down
12 changes: 4 additions & 8 deletions layers/common/utils/element-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
* @param element the element Ref or id
* @returns the element
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function selectElement<T = HTMLElement>(element: Ref<any> | string): T {
export function selectElement<T = HTMLElement>(element: Ref<SafeAny> | string): T {
return typeof element === 'string'
? document.getElementById(element)
: element.value.$el;
Expand All @@ -16,11 +15,9 @@ export function selectElement<T = HTMLElement>(element: Ref<any> | string): T {
* @param element the element Ref or id
* @param method the focus method name, if not found, use focus()
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function focusElement(element: Ref<any> | string, method = 'setFocus') {
export function focusElement(element: Ref<SafeAny> | string, method = 'setFocus') {
return nextTick(() => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const ele = selectElement(element) as any;
const ele = selectElement(element) as SafeAny;

if (typeof ele[method] === 'function') {
ele[method]();
Expand All @@ -38,8 +35,7 @@ export function focusElement(element: Ref<any> | string, method = 'setFocus') {
* @param element the element Ref or id
* @param vertical vertical alignment of the element
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function scrollElement(element: Ref<any> | string, vertical: 'center' | 'end' | 'nearest' | 'start' = 'center') {
export function scrollElement(element: Ref<SafeAny> | string, vertical: 'center' | 'end' | 'nearest' | 'start' = 'center') {
return nextTick(() => {
const ele = selectElement(element);
ele.scrollIntoView({ behavior: 'smooth', block: vertical });
Expand Down
12 changes: 4 additions & 8 deletions layers/common/utils/safe-converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ export function isVoid(arg: unknown) {
* @param defaults default value if null/undefined
* @returns
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function safeString(valOrFun: any, defaults: string = ''): string {
export function safeString(valOrFun: SafeAny, defaults: string = ''): string {
return safeConvert(valOrFun, defaults, (value) => {
switch (typeof value) {
case 'string':
Expand Down Expand Up @@ -282,8 +281,7 @@ export function safeValue<T, D>(valOrFun: Maybe<T | T[]> | (() => Maybe<T | T[]>
* @param defaults default value if null/undefined
* @returns
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function safeValues<T>(valOrFun: any, defaults: T[] = []): T[] {
export function safeValues<T>(valOrFun: SafeAny, defaults: T[] = []): T[] {
return safeConvert(valOrFun, defaults, Object.values);
}

Expand All @@ -294,8 +292,7 @@ export function safeValues<T>(valOrFun: any, defaults: T[] = []): T[] {
* @param defaults default value if null/undefined
* @returns
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function safeKeys(valOrFun: any, defaults: string[] = []): string[] {
export function safeKeys(valOrFun: SafeAny, defaults: string[] = []): string[] {
return safeConvert(valOrFun, defaults, Object.keys);
}

Expand All @@ -306,8 +303,7 @@ export function safeKeys(valOrFun: any, defaults: string[] = []): string[] {
* @param defaults default value if null/undefined
* @returns
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function safeEntries<T>(valOrFun: any, defaults: [string, T][] = []): [string, T][] {
export function safeEntries<T>(valOrFun: SafeAny, defaults: [string, T][] = []): [string, T][] {
return safeConvert(valOrFun, defaults, Object.entries);
}

Expand Down
7 changes: 3 additions & 4 deletions layers/common/utils/typed-fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ export type TypedFetchOptions = {
* catch of try fetching
* @param err any caught error
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
catches?: (err: any) => void;

catches?: (err: SafeAny) => void;
};

function _doLoading(status: LoadingStatus, loading?: Ref<boolean> | ((status: LoadingStatus) => void)): void {
Expand All @@ -39,8 +39,7 @@ function _doResult<T>(failure?: (message?: string, code?: string) => void, resul
return result;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function _doError(err: any, catches?: (err: any) => void): void {
function _doError(err: SafeAny, catches?: (err: SafeAny) => void): void {
if (catches) {
catches(err);
}
Expand Down
12 changes: 4 additions & 8 deletions layers/mobile/tests/ionic-fetcher.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ describe('ionicFetchingDataAsync', () => {
it('should show loading while fetching and dismiss loading after fetching', async () => {
const loadingUiMock = { present: vi.fn(), dismiss: vi.fn() };

// eslint-disable-next-line @typescript-eslint/no-explicit-any
(loadingController.create as any).mockResolvedValue(loadingUiMock);
(loadingController.create as SafeAny).mockResolvedValue(loadingUiMock);

const fetching = Promise.resolve({ success: true, data: 'test-data' } as DataResult<string>);

Expand All @@ -41,8 +40,7 @@ describe('ionicFetchingDataAsync', () => {
it('should handle failure by showing an alert when fetching fails', async () => {
const alertMock = { present: vi.fn() };

// eslint-disable-next-line @typescript-eslint/no-explicit-any
(alertController.create as any).mockResolvedValue(alertMock);
(alertController.create as SafeAny).mockResolvedValue(alertMock);

const fetching = Promise.resolve({ success: false, message: 'Fetch error', code: '404' } as DataResult<string>);

Expand All @@ -58,8 +56,7 @@ describe('ionicFetchingDataAsync', () => {

it('should handle catches by showing an alert when an error is thrown', async () => {
const alertMock = { present: vi.fn() };
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(alertController.create as any).mockResolvedValue(alertMock);
(alertController.create as SafeAny).mockResolvedValue(alertMock);

const fetching = Promise.reject(new Error('Network error'));

Expand All @@ -85,8 +82,7 @@ describe('ionicFetchingDataAsync', () => {

it('should call alertFailure when fetching fails and loading Ref is provided', async () => {
const alertMock = { present: vi.fn() };
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(alertController.create as any).mockResolvedValue(alertMock);
(alertController.create as SafeAny).mockResolvedValue(alertMock);

const loadingRef = ref(true);
const fetching = Promise.resolve({ success: false, message: 'Fetch error', code: '500' } as DataResult<string>);
Expand Down
3 changes: 1 addition & 2 deletions layers/mobile/utils/ionic-fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ function _failure(message?: string, code?: string) {
});
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function _catches(err: any) {
function _catches(err: SafeAny) {
alertController.create({
header: 'Failed to fetch data',
message: err.message || 'Network error',
Expand Down
3 changes: 1 addition & 2 deletions layers/mobile/utils/ionic-validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@
export type IonInputEvent = CustomEvent & { detail: { value?: string | null } };

export function ionicValidateInput(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
inputRef: Ref<any>,
inputRef: Ref<SafeAny>,
checkFun: RegExp | ((value: string, event?: IonInputEvent) => boolean),
modelRef?: Ref<string>,
): (ev?: IonInputEvent | string | null) => boolean | null {
Expand Down

0 comments on commit 1d4ca29

Please sign in to comment.