While I do appreciate the approach... I would note that if you're using TypeScript in a supporting editor (VS Code, for example), the initial approach is pretty reasonable.
Another bit worth mentioning... is the F# style pipeline operator proposal, if you're using Babel. [1]
1. https://github.com/tc39/proposal-pipeline-operator
Given the ability to effectively DDoS a server, I'd say it's indeed a threat.
Even in some validation libraries, you'll find some really poor evaluations. For example, doing input validation while typing on an email input field can get pretty nasty, pretty quickly in a couple of the validation frameworks I've used. It was faster/easier to use a simpler validation first, before the more broad validation... (splitting on '@', checking for 2 parts, length and verifying the parts separately), even limiting the length before/after the '@' in practical terms. Of course, this was only a client-side issue... but it's still an issue.
For a fast build experience, consider esbuild + nodemon. I haven't played with vite specifically, but have with Rollup, and still quite a bit slower than esbuild, if I'm looking for something beyond webpack/rollup or parcel as a wrapper.
The only other complaint(s) I have about this are the typical organized by type, not need/feature/problem and no testing pattern/framework in place.
Do *NOT* use a css file for this... use makeStyles and put it in/with your component. const useStyles = makeStyles((theme) => ({ moreLinks: { width: '100%', borderRadius: 30, fontWeight: '700', justifyContent: 'unset', fontSize: 20, marginRight: 20, textTransform: 'inherit', color: 'black', height: 60, paddingLeft: 10, paddingRight: 30, marginBottom: 5, '& .MuiSvgIcon-root': { marginRight: 10, }, '&:hover': { // ... } // ... } })); // inside component const classes = useStyles // ... passdown className to child render <SidebarLink className={classes.moreLinks} text="More" Icon={MoreHorizIcon} />