Skip to content

Instantly share code, notes, and snippets.

@kadet1090
Created January 21, 2021 22:04
Show Gist options
  • Save kadet1090/8e5128343a4793be1473208e4cfb2f91 to your computer and use it in GitHub Desktop.
Save kadet1090/8e5128343a4793be1473208e4cfb2f91 to your computer and use it in GitHub Desktop.
Catamorphism in typescript
import React from "react";
interface FileItem {
type: "file";
fileName: string;
fileSize: number;
}
interface DirectoryItem<TItem> {
type: "directory";
dirName: string;
dirSize: number;
items: TItem[];
}
type FileSystemItem = FileItem | DirectoryItem<FileSystemItem>;
type FileSystemItemType = FileSystemItem["type"];
const fs = { type: "directory", dirName: "root", dirSize: 5, items: [
{ type: "directory", dirName: "bin", dirSize: 10, items: [] },
{ type: "directory", dirName: "src", dirSize: 10, items: [
{ type: "file", fileName: "readme.txt", fileSize: 1 },
{ type: "file", fileName: "config.xml", fileSize: 2 },
{ type: "file", fileName: "build.bat", fileSize: 3 },
] },
] } as FileSystemItem;
function cataFS<TResult>(
fFile: (file: FileItem) => TResult,
fDirectory: (dir: DirectoryItem<TResult>) => TResult,
item: FileSystemItem
): TResult {
const recurse = (item: FileSystemItem) => cataFS(fFile, fDirectory, item);
switch (item.type) {
case "file":
return fFile(item);
case "directory":
return fDirectory({ ...item, items: item.items.map(recurse) })
}
}
const sizeOfFile = (file: FileItem) => file.fileSize;
const sizeOfDirectory = (dir: DirectoryItem<number>) => dir.dirSize + dir.items.reduce((a, b) => a + b, 0);
const sizeOfItem = (item: FileSystemItem) => cataFS(sizeOfFile, sizeOfDirectory, item);
console.log(sizeOfItem(fs)); // 31
const renderFile = (file: FileItem) => <div>
<b>{ file.fileName }</b> (rozmiar: {file.fileName})
</div>
const renderDirectory = (dir: DirectoryItem<JSX.Element>) => <div>
<b>{ dir.dirName }</b> (rozmiar: {dir.dirName})
<ul>{ dir.items }</ul>
</div>
const FileTree = ({ root }: { root: FileSystemItem }) => cataFS(renderFile, renderDirectory, root);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment