I spent about 2 hours on this assignment. Most of the time was spent configuring the project correctly and debugging issues related to TypeScript compilation, database setup, and test failures.
The area where I spent the most time was designing the API endpoints and making sure they followed REST conventions, especially handling edge cases such as deleting authors that still have books associated with them.
The most challenging part of the assignment was configuration and environment setup, particularly ensuring that TypeScript, SQLite, and Vitest all worked together correctly on Windows. Having clearer starter configuration files would have improved the experience.
TypeScript helped catch several bugs early, such as accessing possibly undefined values from database queries and mismatches between request body shapes and expected types.
However, TypeScript did not catch issues related to runtime behavior, such as incorrect SQL queries or unexpected ordering of query results. These issues only appeared during testing.
The most difficult parts to type correctly were Express request
parameters and query strings, since they often start as
unknown or string | undefined.
I am still becoming more comfortable with narrowing types
and designing helper functions to make this cleaner.
Writing tests was initially tedious, but became rewarding once the structure was in place. Having a consistent pattern for resetting the database before each test made the tests reliable and easy to reason about.
The tests helped uncover multiple bugs, including incorrect HTTP status codes, missing validation checks, and incorrect assumptions about result ordering from SQL queries.
In the future, I would write tests earlier in the process and rely on them more heavily while implementing each request handler incrementally.
I used an LLM as a debugging and learning aid, primarily to clarify TypeScript errors, SQL behavior, and REST API design decisions. I did not rely on it to generate the solution.
Using an LLM made the process less frustrating and helped me move past configuration issues more quickly, allowing me to focus on understanding the architecture and logic of the system.
Overall, it saved time and reduced friction, but I still had to understand and adapt the suggestions in order to make the code work correctly in my specific environment.