Skip to content

Commit a6d6bc3

Browse files
committed
add more types
1 parent 2634902 commit a6d6bc3

File tree

10 files changed

+84
-90
lines changed

10 files changed

+84
-90
lines changed

components/BlogPage/index.tsx

+2-10
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,15 @@
22
import Link from 'next/link';
33
import Layout from 'components/Layout';
44
import PostList from 'components/PostList';
5-
import { Breadcrumb, Post } from 'interfaces';
6-
7-
type BlogPageProps = {
8-
posts: Array<Post>;
9-
currentCategory: string;
10-
socialMeta: object;
11-
categories: Array<string>;
12-
breadcrumbs: Array<Breadcrumb>;
13-
};
5+
import { BlogProps } from 'interfaces';
146

157
const BlogPage = ({
168
posts,
179
currentCategory,
1810
socialMeta,
1911
categories,
2012
breadcrumbs
21-
}: BlogPageProps) => (
13+
}: BlogProps) => (
2214
<Layout socialMeta={socialMeta} breadcrumbs={breadcrumbs}>
2315
<div className='container'>
2416
<h2 className='section__title'>Blog</h2>

components/Layout/index.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import PropTypes from 'prop-types';
21
import Head from 'next/head';
32
import generateBreadcrumbs from 'helpers/generate-breadcrumbs';
43
import generateSocialMeta from 'helpers/generate-social-meta';
@@ -11,7 +10,7 @@ type LayoutProps = {
1110
socialMeta?: SocialMeta;
1211
canonical?: string;
1312
refreshUrl?: string;
14-
structured?: Array<string>;
13+
structured?: Array<string | null>;
1514
children?: React.ReactNode;
1615
};
1716

components/ProgressiveImage/index.tsx

+6-9
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
import React, { useState, useEffect } from 'react';
22
import isExternalImage from 'helpers/is-external-image';
33

4-
type ProgressiveImageProps = {
5-
src: string;
6-
alt: string;
7-
style?: object;
8-
className?: string;
9-
};
10-
11-
const ProgressiveImage = (props: ProgressiveImageProps) => {
4+
const ProgressiveImage = (
5+
props: React.DetailedHTMLProps<
6+
React.ImgHTMLAttributes<HTMLImageElement>,
7+
HTMLImageElement
8+
>
9+
) => {
1210
const isExternal = isExternalImage(props.src);
1311

1412
const [currentImage, setCurrentImage] = useState(
@@ -37,7 +35,6 @@ const ProgressiveImage = (props: ProgressiveImageProps) => {
3735

3836
return (
3937
<img
40-
{...props}
4138
style={{ ...props.style, ...style() }}
4239
src={currentImage}
4340
alt={props.alt}

helpers/generate-faq-structured-data.js helpers/generate-faq-structured-data.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
const generateFaqStructuredData = faq => {
1+
import { Faq } from '../interfaces';
2+
3+
const generateFaqStructuredData = (faq: Faq) => {
24
if (!faq) return null;
35

46
const json = {

interfaces/index.ts

+33
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,28 @@
1+
import { ParsedUrlQuery } from 'querystring';
2+
3+
export type FaqItem = {
4+
question: string;
5+
answer: string;
6+
}
7+
8+
export type Faq = Array<FaqItem> | null;
19
export type Post = {
210
slug: string;
311
intro: string;
412
date: string;
13+
tags: string;
514
description: string;
615
title: string;
16+
cover_image_alt: string;
17+
cover_image: string;
18+
faq: Faq;
19+
oldBlog?: boolean;
720
};
821

22+
export interface StaticPropsContextParams extends ParsedUrlQuery {
23+
slug: string;
24+
}
25+
926
export type Breadcrumb = {
1027
item: string;
1128
name: string;
@@ -32,3 +49,19 @@ export type Project = {
3249
export type RequireContext = {
3350
[x: string]: any;
3451
}
52+
53+
export interface BlogPostProps extends Post {
54+
image: string;
55+
markdownBody: string;
56+
frontmatter: Post;
57+
siteTitle: string;
58+
}
59+
60+
export type BlogProps = {
61+
title: string;
62+
posts: Array<Post>;
63+
currentCategory: string;
64+
socialMeta: SocialMeta;
65+
categories: Array<string>;
66+
breadcrumbs: Array<Breadcrumb>;
67+
};

pages/about.tsx

+1-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { GetStaticProps } from 'next';
2-
import PropTypes from 'prop-types';
32
import Layout from 'components/Layout';
43
import ProgressiveImage from 'components/ProgressiveImage';
54
import styles from 'styles/about.module.scss';
@@ -11,11 +10,7 @@ const socialMeta = {
1110
url: 'about'
1211
};
1312

14-
type AboutProps = {
15-
title: string;
16-
};
17-
18-
const About = ({ title }: AboutProps) => (
13+
const About = ({ title }: { title: string }) => (
1914
<Layout
2015
socialMeta={{ ...socialMeta, title }}
2116
breadcrumbs={[{ name: 'about', item: 'about/' }]}
@@ -64,8 +59,6 @@ const About = ({ title }: AboutProps) => (
6459
</Layout>
6560
);
6661

67-
About.propTypes = { title: PropTypes.string };
68-
6962
export default About;
7063

7164
export const getStaticProps: GetStaticProps = async () => {

pages/blog.tsx

+2-11
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { GetStaticProps } from 'next';
22
import BlogPage from 'components/BlogPage';
33
import parsePosts from 'helpers/parse-posts';
44
import getCategories from 'helpers/get-categories';
5-
import { Post, Breadcrumb } from 'interfaces';
5+
import { BlogProps } from 'interfaces';
66

77
const socialMeta = {
88
image:
@@ -13,16 +13,7 @@ const socialMeta = {
1313
url: 'blog'
1414
};
1515

16-
type IndexProps = {
17-
title: string;
18-
posts: Array<Post>;
19-
currentCategory: string;
20-
socialMeta: object;
21-
categories: Array<string>;
22-
breadcrumbs: Array<Breadcrumb>;
23-
};
24-
25-
const Index = (props: IndexProps) => (
16+
const Index = (props: BlogProps) => (
2617
<BlogPage
2718
{...props}
2819
socialMeta={{ ...socialMeta, title: props.title }}

pages/blog/[postname].js pages/blog/[postname].tsx

+11-17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable global-require */
22
/* eslint-disable import/no-dynamic-require */
3-
import PropTypes from 'prop-types';
3+
import { GetStaticProps } from 'next';
44
import matter from 'gray-matter';
55
import ReactMarkdown from 'react-markdown';
66
import remarkGfm from 'remark-gfm';
@@ -14,15 +14,16 @@ import isExternalImage from 'helpers/is-external-image';
1414
import generateArticleStructuredData from 'helpers/generate-article-structured-data';
1515
import generateFaqStructuredData from 'helpers/generate-faq-structured-data';
1616
import parsePosts from 'helpers/parse-posts';
17+
import { Post, StaticPropsContextParams, BlogPostProps } from 'interfaces';
1718

18-
export default function BlogPost({
19+
export const BlogPost = ({
1920
siteTitle,
2021
frontmatter,
2122
markdownBody,
2223
date,
2324
slug,
2425
image
25-
}) {
26+
}: BlogPostProps) => {
2627
// eslint-disable-next-line react/jsx-no-useless-fragment
2728
if (!frontmatter) return <></>;
2829

@@ -101,22 +102,15 @@ export default function BlogPost({
101102
</article>
102103
</Layout>
103104
);
104-
}
105-
106-
BlogPost.propTypes = {
107-
siteTitle: PropTypes.string,
108-
frontmatter: PropTypes.object,
109-
markdownBody: PropTypes.string,
110-
date: PropTypes.array,
111-
slug: PropTypes.string,
112-
image: PropTypes.string
113105
};
114106

115-
export async function getStaticProps({ ...ctx }) {
116-
const { postname } = ctx.params;
107+
export default BlogPost;
108+
109+
export const getStaticProps: GetStaticProps = async context => {
110+
const { postname = '' } = context.params as StaticPropsContextParams;
117111
const content = await import(`../../posts/${postname}.md`);
118112
const config = await import('../../siteconfig.json');
119-
const date = postname.match(/(\d{1,4}([.\--])\d{1,2}([.\--])\d{1,4})/g);
113+
const date = `${postname}`.match(/(\d{1,4}([.\--])\d{1,2}([.\--])\d{1,4})/g);
120114
const data = matter(content.default);
121115
let image = data.data.cover_image || null;
122116

@@ -141,9 +135,9 @@ export async function getStaticProps({ ...ctx }) {
141135
export async function getStaticPaths() {
142136
const allPosts = parsePosts(
143137
require.context('../../posts', true, /\.\/.*\.md$/)
144-
).map(post => post.slug);
138+
).map((post: Post) => post.slug);
145139

146-
const paths = allPosts.map(slug => `/blog/${slug}`);
140+
const paths = allPosts.map((slug: string) => `/blog/${slug}`);
147141

148142
return {
149143
paths,

pages/blog/category/[categoryname].js pages/blog/category/[categoryname].tsx

+14-14
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
import PropTypes from 'prop-types';
1+
import { GetStaticProps } from 'next';
22
import matter from 'gray-matter';
33
import BlogPage from 'components/BlogPage';
44
import parsePosts from 'helpers/parse-posts';
55
import getCategories from 'helpers/get-categories';
6+
import { Post, StaticPropsContextParams, BlogProps } from 'interfaces';
67

78
const socialMeta = {
89
image:
910
'https://khendrikse.github.io/_next/static/chunks/images/portait-linoosk-db0fc2adaa55eb6080c20ff88376c1ba.png',
1011
imageAlt: 'Drawn avatar of khendrikse'
1112
};
1213

13-
const Index = props => (
14+
const Index = (props: BlogProps) => (
1415
<BlogPage
1516
{...props}
1617
socialMeta={{
@@ -19,37 +20,36 @@ const Index = props => (
1920
description: `Blog about ${props.currentCategory}`,
2021
title: props.title
2122
}}
22-
breadcrumbs={[{ name: 'blog', item: `blog/category/${props.currentCategory}` }]}
23+
breadcrumbs={[
24+
{ name: 'blog', item: `blog/category/${props.currentCategory}` }
25+
]}
2326
/>
2427
);
2528

26-
Index.propTypes = {
27-
title: PropTypes.string,
28-
currentCategory: PropTypes.string
29-
};
30-
3129
export default Index;
3230

33-
export async function getStaticProps({ ...ctx }) {
34-
const { categoryname } = ctx.params;
31+
export const getStaticProps: GetStaticProps = async context => {
32+
const { categoryname = '' } = context.params as StaticPropsContextParams;
3533
const allPosts = parsePosts(
3634
require.context('../../../posts', true, /\.\/.*\.md$/)
3735
);
3836

3937
const categories = getCategories(allPosts);
40-
const posts = allPosts.filter(post => post?.tags?.includes(categoryname));
38+
const posts = allPosts.filter((post: Post) =>
39+
post?.tags?.includes(`${categoryname}`)
40+
);
4141

4242
const config = await import('../../../siteconfig.json');
4343

4444
return {
4545
props: {
46-
title: 'Blog - '.concat(categoryname, ' | ', config.title),
46+
title: 'Blog - '.concat(`${categoryname}`, ' | ', config.title),
4747
categories,
4848
posts,
4949
currentCategory: categoryname
5050
}
5151
};
52-
}
52+
};
5353

5454
export async function getStaticPaths() {
5555
const posts = await (async context => {
@@ -63,7 +63,7 @@ export async function getStaticPaths() {
6363
})(require.context('../../../posts', true, /\.\/.*\.md$/));
6464
const categorySlugs = getCategories(posts);
6565

66-
const paths = categorySlugs.map(slug => `/blog/category/${slug}`);
66+
const paths = categorySlugs.map((slug: string) => `/blog/category/${slug}`);
6767

6868
return {
6969
paths,

pages/post/[postname].js pages/post/[postname].tsx

+11-18
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable global-require */
22
/* eslint-disable import/no-dynamic-require */
3-
import PropTypes from 'prop-types';
3+
import { GetStaticProps } from 'next';
44
import matter from 'gray-matter';
55
import ReactMarkdown from 'react-markdown';
66
import remarkGfm from 'remark-gfm';
@@ -14,6 +14,7 @@ import isExternalImage from 'helpers/is-external-image';
1414
import generateArticleStructuredData from 'helpers/generate-article-structured-data';
1515
import generateFaqStructuredData from 'helpers/generate-faq-structured-data';
1616
import parsePosts from '../../helpers/parse-posts';
17+
import { Post, StaticPropsContextParams, BlogPostProps } from 'interfaces';
1718

1819
export default function BlogPost({
1920
siteTitle,
@@ -22,7 +23,7 @@ export default function BlogPost({
2223
date,
2324
slug,
2425
image
25-
}) {
26+
}: BlogPostProps) {
2627
// eslint-disable-next-line react/jsx-no-useless-fragment
2728
if (!frontmatter) return <></>;
2829

@@ -105,23 +106,15 @@ export default function BlogPost({
105106
);
106107
}
107108

108-
BlogPost.propTypes = {
109-
siteTitle: PropTypes.string,
110-
frontmatter: PropTypes.object,
111-
markdownBody: PropTypes.string,
112-
date: PropTypes.array,
113-
slug: PropTypes.string,
114-
image: PropTypes.string
115-
};
109+
export const getStaticProps: GetStaticProps = async context => {
110+
const { postname = '' } = context.params as StaticPropsContextParams;
116111

117-
export async function getStaticProps({ ...ctx }) {
118-
const { postname } = ctx.params;
119-
const slug = postname
112+
const slug = `${postname}`
120113
.replace(/(\d{1,4}([.\--])\d{1,2}([.\--])\d{1,4})/g, '')
121114
.substring(1);
122115
const content = await import(`../../posts/${slug}.md`);
123116
const config = await import('../../siteconfig.json');
124-
const date = postname.match(/(\d{1,4}([.\--])\d{1,2}([.\--])\d{1,4})/g);
117+
const date = `${postname}`.match(/(\d{1,4}([.\--])\d{1,2}([.\--])\d{1,4})/g);
125118
const data = matter(content.default);
126119
let image = data.data.cover_image || null;
127120

@@ -141,16 +134,16 @@ export async function getStaticProps({ ...ctx }) {
141134
image
142135
}
143136
};
144-
}
137+
};
145138

146139
export async function getStaticPaths() {
147140
const allPosts = parsePosts(
148141
require.context('../../posts', true, /\.\/.*\.md$/)
149142
)
150-
.filter(post => post.oldBlog)
151-
.map(post => post.date.concat('-', post.slug));
143+
.filter((post: Post) => post.oldBlog)
144+
.map((post: Post) => post.date.concat('-', post.slug));
152145

153-
const paths = allPosts.map(slug => `/post/${slug}`);
146+
const paths = allPosts.map((slug: string) => `/post/${slug}`);
154147

155148
return {
156149
paths,

0 commit comments

Comments
 (0)