[Typescript] Using tiny-invariant for narrowing type
import { json } from "remix"; import path from "path"; import fs from "fs/promises"; import parseFrontMatter from "front-matter"; import invariant from "tiny-invariant"; import { marked } from "marked"; export type Post = { slug: string; title: string; html: string; }; export type PostMarkdownAttributes = { title: string; }; type NewPost = { title: string; slug: string; markdown: string; }; function isValidPostAttributes( attributes: any ): attributes is PostMarkdownAttributes { return attributes?.title; } const postsPath = path.join(__dirname, "..", "posts"); export async function getPost(slug: string): Promise<Post> { const filepath = path.join(postsPath, slug + ".md"); const file = await fs.readFile(filepath); const { attributes, body } = parseFrontMatter(file.toString()); invariant( isValidPostAttributes(attributes), `Post ${filepath} is missing attributes` ); const html = marked(body); return { slug, html, title: attributes.title }; }
export const action: ActionFunction = async ({ request }) => { const formData = await request.formData(); await new Promise((res) => setTimeout(res, 1000)); const title = formData.get("title"); const slug = formData.get("slug"); const markdown = formData.get("markdown"); const errors: PostError = {}; if (!title) errors.title = true; if (!slug) errors.slug = true; if (!markdown) errors.markdown = true; if (Object.keys(errors).length) { return json(errors); } invariant(typeof title === "string"); invariant(typeof slug === "string"); invariant(typeof markdown === "string"); await createPost({ title, slug, markdown }); return redirect("/admin"); };