Skip to content

Commit 60e21c3

Browse files
committed
fix: Remove 'any' types from utilities, libraries, and tests
1 parent d141e96 commit 60e21c3

14 files changed

+326
-168
lines changed

cypress/components/DocsHelp.cy.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const FEEDBACK_FORM_GITHUB_SUCCESS_MESSAGE =
2020
describe('DocsHelp Component', () => {
2121
// eslint-disable-next-line @typescript-eslint/no-unused-vars
2222
let mockRouter: MockRouter;
23-
const extractPathWithoutFragment = (path: any) => path.split('#')[0];
23+
const extractPathWithoutFragment = (path: string) => path.split('#')[0];
2424
// Note: we are not using the mockRouter in this test file, but it is required to mock the router in the component file
2525

2626
beforeEach(() => {

cypress/components/Sidebar.cy.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ describe('Sidebar Component', () => {
135135
});
136136

137137
describe('DocsNav', () => {
138-
let mockSetOpen: any;
138+
let mockSetOpen: Cypress.Agent<sinon.SinonStub>;
139139

140140
beforeEach(() => {
141141
mockSetOpen = cy.stub().as('setOpen');

cypress/plugins/mockNextRouterUtils.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@
44
*/
55

66
export interface MockRouter {
7-
push: any;
8-
replace: any;
9-
prefetch: any;
7+
push: Cypress.Agent<sinon.SinonStub>;
8+
replace: Cypress.Agent<sinon.SinonStub>;
9+
prefetch: Cypress.Agent<sinon.SinonStub>;
1010
pathname: string;
11-
query: Record<string, any>;
11+
query: Record<string, string | string[]>;
1212
asPath: string;
1313
events: {
14-
on: any;
15-
off: any;
16-
emit: any;
14+
on: Cypress.Agent<sinon.SinonStub>;
15+
off: Cypress.Agent<sinon.SinonStub>;
16+
emit: Cypress.Agent<sinon.SinonStub>;
1717
};
1818
}
1919

lib/calendarUtils.ts

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import moment from 'moment-timezone';
2+
import type { CalendarResponse, VEvent } from 'node-ical';
23

34
export async function fetchRemoteICalFile(url: string): Promise<string | null> {
45
try {
@@ -13,11 +14,25 @@ export async function fetchRemoteICalFile(url: string): Promise<string | null> {
1314
}
1415
}
1516

16-
export function printEventsForNextWeeks(icalData: { [x: string]: any }) {
17-
const arrayDates = [];
17+
function isVEvent(component: CalendarResponse[string]): component is VEvent {
18+
return component.type === 'VEVENT';
19+
}
20+
21+
export interface CalendarEventInfo {
22+
title: string | undefined;
23+
time: string;
24+
day: string;
25+
timezone: string;
26+
parsedStartDate: string;
27+
}
28+
29+
export function printEventsForNextWeeks(
30+
icalData: CalendarResponse,
31+
): CalendarEventInfo[] {
32+
const arrayDates: CalendarEventInfo[] = [];
1833
if (!icalData) {
1934
console.error('iCal data is empty or invalid.');
20-
return;
35+
return [];
2136
}
2237

2338
// Calculate the range of dates for the next 12 weeks from today
@@ -26,14 +41,18 @@ export function printEventsForNextWeeks(icalData: { [x: string]: any }) {
2641

2742
// Loop through the events in the iCal data
2843
for (const k in icalData) {
29-
const event = icalData[k];
44+
const component = icalData[k];
3045

31-
if (event.type === 'VEVENT') {
46+
if (isVEvent(component)) {
47+
const event = component;
3248
const title = event.summary;
3349

3450
const timezoneL = moment.tz.guess(); // Default to UTC if timezone information is not provided
3551

36-
const startDate = moment.tz(event.start, timezoneL);
52+
const eventStart = event.start;
53+
if (!eventStart) continue;
54+
55+
const startDate = moment.tz(eventStart, timezoneL);
3756

3857
// Complicated case - if an RRULE exists, handle multiple recurrences of the event.
3958
if (event.rrule !== undefined) {
@@ -46,18 +65,19 @@ export function printEventsForNextWeeks(icalData: { [x: string]: any }) {
4665
// Loop through the set of date entries to see which recurrences should be printed.
4766
for (const date of dates) {
4867
const startDate = moment.tz(date, timezoneL);
49-
const eventtimezone = event.start.tz;
68+
const eventtimezone = eventStart.tz ?? 'UTC';
5069
const owntimezone = moment.tz.guess();
5170
const eventOffset = moment.tz(eventtimezone).utcOffset();
5271
const localOffset = moment.tz(owntimezone).utcOffset();
5372
const offsetDifference = localOffset - eventOffset;
5473

5574
// Check if the event falls within the next 4 weeks from today
5675
if (startDate.isBetween(today, nextTwelveWeeksEnd, undefined, '[]')) {
57-
const dateTimezone = moment.tz.zone(event.start.tz);
76+
const dateTimezone = moment.tz.zone(eventtimezone);
5877
let offset;
5978
if (dateTimezone && offsetDifference)
60-
offset = offsetDifference - dateTimezone.utcOffset(date);
79+
offset =
80+
offsetDifference - dateTimezone.utcOffset(date.getTime());
6181

6282
const newDate = moment(date).subtract(offset, 'minutes').toDate();
6383

lib/getPartsOfJson.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,12 @@ const getPartsOfJsonObjectContent = (
220220
stringsWithPayload = [...stringsWithPayload, stringWithPayload];
221221
});
222222

223-
let keywordsAndValue: any[] = [];
223+
let keywordsAndValue: Array<{
224+
index?: number;
225+
keyword?: string;
226+
payload?: string;
227+
payloadStartIndex?: number;
228+
}> = [];
224229

225230
let openCurlyBrackets = 0;
226231
let openSquareBrackets = 0;
@@ -303,6 +308,14 @@ const getPartsOfJsonObjectContent = (
303308
});
304309

305310
return keywordsAndValue.reduce((acc, keywordAndValue) => {
311+
if (
312+
!keywordAndValue.keyword ||
313+
keywordAndValue.index === undefined ||
314+
!keywordAndValue.payload ||
315+
keywordAndValue.payloadStartIndex === undefined
316+
) {
317+
return acc;
318+
}
306319
const propertyJsonPath = `${jsonPath}['${keywordAndValue.keyword}']`;
307320
const objectPropertyStartQuotes: SyntaxPart = {
308321
type: 'objectPropertyStartQuotes',
@@ -340,7 +353,7 @@ const getPartsOfJsonObjectContent = (
340353
objectPropertyEndQuotes,
341354
...partsFromPayload,
342355
];
343-
}, []);
356+
}, [] as SyntaxPart[]);
344357
};
345358

346359
const getPartsOfArrayContent = (

lib/getScopesOfParsedJsonSchema.ts

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,45 @@ export type JsonSchemaPathWithScope = {
77
scope: JsonSchemaScope;
88
};
99

10+
interface ParsedJsonSchema {
11+
type?: string;
12+
properties?: Record<string, unknown>;
13+
patternProperties?: Record<string, unknown>;
14+
items?: unknown;
15+
[key: string]: unknown;
16+
}
17+
1018
export default function getScopesOfParsedJsonSchema(
11-
parsedJsonSchema: any,
19+
parsedJsonSchema: ParsedJsonSchema | unknown,
1220
jsonPath = '$',
1321
): JsonSchemaPathWithScope[] {
1422
if (typeof parsedJsonSchema !== 'object' || parsedJsonSchema === null)
1523
return [];
24+
25+
const schema = parsedJsonSchema as ParsedJsonSchema;
1626
const typeDefinitionScope = {
1727
jsonPath,
1828
scope: JsonSchemaScope.TypeDefinition,
1929
};
20-
if (parsedJsonSchema.type === 'object') {
21-
const scopesOfProperties = Object.keys(
22-
parsedJsonSchema?.properties || {},
23-
).reduce<JsonSchemaPathWithScope[]>((acc, property) => {
30+
if (schema.type === 'object') {
31+
const scopesOfProperties = Object.keys(schema?.properties || {}).reduce<
32+
JsonSchemaPathWithScope[]
33+
>((acc, property) => {
2434
return [
2535
...acc,
2636
...getScopesOfParsedJsonSchema(
27-
parsedJsonSchema.properties?.[property],
37+
schema.properties?.[property],
2838
`${jsonPath}['properties']['${property}']`,
2939
),
3040
];
3141
}, []);
3242
const scopesOfPatternProperties = Object.keys(
33-
parsedJsonSchema?.patternProperties || {},
43+
schema?.patternProperties || {},
3444
).reduce<JsonSchemaPathWithScope[]>((acc, property) => {
3545
return [
3646
...acc,
3747
...getScopesOfParsedJsonSchema(
38-
parsedJsonSchema.patternProperties?.[property],
48+
schema.patternProperties?.[property],
3949
`${jsonPath}['patternProperties']['${property}']`,
4050
),
4151
];
@@ -46,13 +56,10 @@ export default function getScopesOfParsedJsonSchema(
4656
...scopesOfPatternProperties,
4757
];
4858
}
49-
if (parsedJsonSchema.type === 'array') {
59+
if (schema.type === 'array') {
5060
return [
5161
typeDefinitionScope,
52-
...getScopesOfParsedJsonSchema(
53-
parsedJsonSchema.items,
54-
`${jsonPath}['items']`,
55-
),
62+
...getScopesOfParsedJsonSchema(schema.items, `${jsonPath}['items']`),
5663
];
5764
}
5865
return [typeDefinitionScope];

lib/getStaticMarkdownProps.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,19 @@ import matter from 'gray-matter';
33

44
type Props = { params?: { slug: string } };
55

6+
interface Frontmatter {
7+
[key: string]: unknown;
8+
}
9+
610
export default async function getStaticMarkdownProps(
711
props: Props,
812
path: string,
9-
) {
13+
): Promise<{
14+
props: {
15+
frontmatter: Frontmatter;
16+
content: string;
17+
};
18+
}> {
1019
const slug = props.params?.slug || '_index';
1120

1221
const fileName2 = `${path}/${slug}.md`;
@@ -16,7 +25,7 @@ export default async function getStaticMarkdownProps(
1625

1726
return {
1827
props: {
19-
frontmatter,
28+
frontmatter: frontmatter as Frontmatter,
2029
content,
2130
},
2231
};

lib/slugifyMarkdownHeadline.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import slugify from 'slugify';
22

33
export default function slugifyMarkdownHeadline(
4-
markdownChildren: string | any[],
4+
markdownChildren: string | (string | unknown)[],
55
): string {
66
const FRAGMENT_REGEX = /\[#(?<slug>(\w|-|_)*)\]/g;
77
if (!markdownChildren) return '';
88
if (typeof markdownChildren === 'string')
99
return slugify(markdownChildren, { lower: true, trim: true });
10-
const metaSlug = markdownChildren.reduce((acc, child) => {
10+
const metaSlug = markdownChildren.reduce<string | null>((acc, child) => {
1111
if (acc) return acc;
1212
if (typeof child !== 'string') return null;
1313
const fragment = FRAGMENT_REGEX.exec(child);

pages/_app.page.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@ import type { AppProps } from 'next/app';
55
import { ThemeProvider } from 'next-themes';
66

77
function MyApp({ Component, pageProps }: AppProps) {
8-
// @ts-ignore
9-
const getLayout = Component.getLayout || ((page: JSX.Element) => page);
10-
const AnyComponent = Component as any;
8+
// Use type assertion for getLayout since Next.js allows custom properties on components
9+
const getLayout =
10+
(
11+
Component as {
12+
getLayout?: (page: JSX.Element, pageProps?: unknown) => JSX.Element;
13+
}
14+
).getLayout || ((page: JSX.Element) => page);
1115
return (
1216
<ThemeProvider attribute='class'>
13-
{getLayout(<AnyComponent {...pageProps} />, pageProps)}
17+
{getLayout(<Component {...pageProps} />, pageProps)}
1418
</ThemeProvider>
1519
);
1620
}

pages/blog/generateRssFeed.tsx

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,25 @@ import { Feed, Author, Item } from 'feed';
33

44
const SITE_URL = 'https://json-schema.org';
55

6-
export default async function generateRssFeed(blogPosts: any) {
6+
interface BlogPostFrontmatter {
7+
title: string;
8+
excerpt?: string;
9+
cover?: string;
10+
date?: string;
11+
type?: string | string[];
12+
authors?: Array<{
13+
name: string;
14+
twitter?: string;
15+
}>;
16+
}
17+
18+
interface BlogPost {
19+
slug: string;
20+
frontmatter: BlogPostFrontmatter;
21+
content?: string;
22+
}
23+
24+
export default async function generateRssFeed(blogPosts: BlogPost[]) {
725
const today = new Date();
826
const feed = new Feed({
927
title: 'JSON Schema Blog RSS Feed',
@@ -23,9 +41,9 @@ export default async function generateRssFeed(blogPosts: any) {
2341
language: 'en-gb',
2442
});
2543

26-
blogPosts.forEach((post: any) => {
27-
const authors: Author[] = post.frontmatter.authors.map(
28-
(author: any): Author => {
44+
blogPosts.forEach((post) => {
45+
const authors: Author[] = (post.frontmatter.authors || []).map(
46+
(author): Author => {
2947
const link = author.twitter
3048
? `https://x.com/${author.twitter}`
3149
: undefined;
@@ -41,19 +59,29 @@ export default async function generateRssFeed(blogPosts: any) {
4159
title: post.frontmatter.title,
4260
id: url,
4361
link: url,
44-
description: post.frontmatter.excerpt as string,
62+
description: post.frontmatter.excerpt || '',
4563
author: authors,
46-
date: new Date(post.frontmatter.date),
47-
image: {
48-
url: `${SITE_URL}${post.frontmatter.cover}`,
49-
},
50-
category: post.frontmatter.type,
51-
enclosure: {
52-
url: `${SITE_URL}${post.frontmatter.cover}`,
53-
type: 'image',
54-
length: 15026,
55-
},
56-
published: new Date(post.frontmatter.date),
64+
date: new Date(post.frontmatter.date || Date.now()),
65+
/* eslint-disable indent */
66+
image: post.frontmatter.cover
67+
? {
68+
url: `${SITE_URL}${post.frontmatter.cover}`,
69+
}
70+
: undefined,
71+
category: Array.isArray(post.frontmatter.type)
72+
? post.frontmatter.type.map((t) => ({ name: t }))
73+
: post.frontmatter.type
74+
? [{ name: post.frontmatter.type }]
75+
: undefined,
76+
enclosure: post.frontmatter.cover
77+
? {
78+
url: `${SITE_URL}${post.frontmatter.cover}`,
79+
type: 'image',
80+
length: 15026,
81+
}
82+
: undefined,
83+
/* eslint-enable indent */
84+
published: new Date(post.frontmatter.date || Date.now()),
5785
};
5886
feed.addItem(item);
5987
});

0 commit comments

Comments
 (0)