I spent the first few months of using LLMs for coding making the same mistake most of us do. I treated the prompt box like a Google search bar. I would type 'How to implement a debounced search in React' and then copy-paste the first block of code the AI spat out.
It worked 70% of the time. The other 30% was a nightmare of deprecated hooks, weird edge cases, and hallucinations that took me longer to debug than if I had just read the documentation.
Here is the reality: LLMs are not databases. They are pattern matchers. When you ask a general question, you get a general (and often outdated) answer. To get production-ready code, you have to change how you communicate with the model.
The Context Gap
The biggest reason AI gives you bad code is a lack of context. The model does not know your project structure, your TypeScript configuration, or your team's linting rules. When you ask for a snippet, it fills those gaps with the most common patterns it saw during training.
If you are using a modern version of a library but the model was trained on a version from two years ago, it will confidently give you code that throws a syntax error.
Shift to Specification-Driven Prompting
Instead of asking 'How do I do X', start providing the constraints first. I call this specification-driven prompting. You should define the environment, the goal, and the boundaries before you ask for the code.
Try this structure:
- Role: 'You are a senior TypeScript engineer focusing on performance.'
- Context: 'I am using React 18 with Vite and Tailwind CSS.'
- Constraint: 'Do not use external libraries for the debounce logic. Keep it under 20 lines of code.'
- Goal: 'Create a hook that handles a search input with a 300ms delay.'
By narrowing the field, you stop the model from guessing. You are effectively telling it which part of its training data to ignore.
The Iterative Refinement Loop
One of the worst habits is the 'one-shot' attempt. If the first response is slightly off, most devs just tweak the prompt and try again from scratch.
Instead, treat it like a code review. If the AI gives you a function that is almost right but misses a null check, do not rewrite the whole prompt. Tell it: 'The logic is correct, but it will crash if the API returns a 404. Add a guard clause for that.'
This iterative approach does two things. First, it keeps the conversation focused on the specific problem. Second, it forces you to actually read the code rather than blindly trusting the output.
Handling Hallucinations in Libraries
We have all seen it: the AI suggests a method like .toFormattedJSON() that does not actually exist in the library. This happens because the model sees similar patterns in other libraries and assumes it exists here too.
To stop this, I started a habit of pasting the actual documentation for the specific function I am struggling with into the prompt.
'Here is the documentation for the SDK method: [Paste Text]. Based on this specific API, how should I handle the authentication flow?'
When you provide the source of truth, the AI stops guessing and starts processing. You move from 'creative writing' mode to 'logic processing' mode.
The Hard Truth about AI Coding
AI is a force multiplier, but it multiplies whatever you put into it. If you put in lazy, vague prompts, you get lazy, buggy code. If you put in precise specifications, you get a tool that handles the boilerplate so you can focus on the architecture.
Concrete Takeaway
Stop using single-sentence prompts. Use the 'Role, Context, Constraint, Goal' framework. If the code looks too perfect to be true, it is probably using a library method that does not exist. Always provide the documentation snippet for niche libraries to eliminate hallucinations.
Top comments (0)