Using Copilot Chat for Explanations and Refactoring
Copilot Chat extends beyond code completion to provide a conversational interface for understanding, explaining, and improving your code. It's like having a knowledgeable colleague available 24/7.
Accessing Copilot Chat
VS Code
- Chat Panel: Click the Copilot icon in the sidebar or press
Ctrl+Shift+I/Cmd+Shift+I - Inline Chat: Select code and press
Ctrl+I/Cmd+Ifor contextual chat - Quick Chat: Press
Ctrl+Shift+Pand type "Copilot Chat"
JetBrains IDEs
- Chat Panel: Go to View → Tool Windows → GitHub Copilot Chat
- Inline: Select code, right-click, and choose GitHub Copilot → Start Chat
Chat Commands (Slash Commands)
Copilot Chat supports special commands that trigger specific behaviors:
| Command | Purpose | Example |
|---|---|---|
/explain | Explain selected code | /explain this recursive function |
/fix | Suggest fixes for problems | /fix this null pointer error |
/tests | Generate tests | /tests for the UserService class |
/doc | Generate documentation | /doc for this API endpoint |
/simplify | Simplify complex code | /simplify this nested conditional |
/optimize | Improve performance | /optimize this database query |
/new | Start a new chat session | /new |
/clear | Clear chat history | /clear |
Explaining Code
Understanding Unfamiliar Code
Select confusing code and ask Copilot to explain it:
// Select this code and type: /explain
const debounce = (fn, delay) => {
let timeoutId;
return (...args) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn.apply(this, args), delay);
};
};
Copilot will explain:
- What debouncing is and why it's useful
- How the closure captures
timeoutId - What
fn.apply(this, args)does - When you'd use this pattern
Understanding Error Messages
Paste an error and ask for help:
"I'm getting this error:
TypeError: Cannot read property 'map' of undefined
Here's my code:
function renderItems(items) {
return items.map(item => <li>{item.name}</li>);
}
What's wrong and how do I fix it?"
Copilot explains the issue (items might be undefined) and suggests solutions like default parameters or optional chaining.
Refactoring with Chat
Inline Chat Refactoring
Select code, press Ctrl+I / Cmd+I, and describe the refactoring:
# Original code - select it
if status == 'active':
return True
elif status == 'inactive':
return False
elif status == 'pending':
return None
else:
raise ValueError('Unknown status')
# Type: "Convert to a dictionary lookup"
# Copilot suggests:
STATUS_MAP = {
'active': True,
'inactive': False,
'pending': None,
}
def get_status_value(status):
if status not in STATUS_MAP:
raise ValueError('Unknown status')
return STATUS_MAP[status]
Common Refactoring Requests
Convert callback to async/await:
// Ask: "Convert this callback-based code to async/await"
// Before:
function fetchData(callback) {
api.get('/data', (err, response) => {
if (err) callback(err);
else callback(null, response.data);
});
}
// After (Copilot suggestion):
async function fetchData() {
const response = await api.get('/data');
return response.data;
}
Extract function:
# Ask: "Extract the validation logic into a separate function"
# Before:
def process_order(order):
if not order.get('items'):
raise ValueError('Order must have items')
if order.get('total', 0) <= 0:
raise ValueError('Order total must be positive')
# ... rest of processing
# After:
def validate_order(order):
if not order.get('items'):
raise ValueError('Order must have items')
if order.get('total', 0) <= 0:
raise ValueError('Order total must be positive')
def process_order(order):
validate_order(order)
# ... rest of processing
Add error handling:
// Ask: "Add proper error handling to this async function"
// Before:
async function saveUser(user: User) {
const result = await database.insert('users', user);
return result;
}
// After:
async function saveUser(user: User): Promise<SaveResult> {
try {
const result = await database.insert('users', user);
return { success: true, data: result };
} catch (error) {
console.error('Failed to save user:', error);
return { success: false, error: error.message };
}
}
Code Reviews with Chat
Ask Copilot to review your code for issues:
"Review this function for potential bugs, security issues, and improvements:
function authenticateUser(username, password) {
const query = `SELECT * FROM users WHERE username = '${username}' AND password = '${password}'`;
const user = db.execute(query);
if (user) {
return { token: generateToken(user.id) };
}
return null;
}
"
Copilot might identify:
- SQL injection vulnerability (string interpolation in query)
- Plain text password storage issue
- Missing input validation
- No rate limiting
Architecture and Design Discussions
Use Chat for higher-level discussions:
"I'm building a notification system that needs to:
- Send emails, SMS, and push notifications
- Handle retries for failed deliveries
- Support scheduling notifications for later
- Track delivery status
What design patterns would you recommend? Should I use a queue?"
Copilot can discuss:
- Strategy pattern for different notification channels
- Queue systems like Redis or RabbitMQ
- Retry strategies with exponential backoff
- Database schema for tracking status
Contextual Questions
Copilot Chat understands your open files and workspace:
"Looking at my current file:
- What does the processPayment function do?
- Why is there a retry loop in line 45?
- What happens if the API returns a 429 error?"
It uses the visible code to provide contextual answers.
Multi-Turn Conversations
Build on previous messages for complex tasks:
You: "How should I structure a REST API for a todo app?"
Copilot: [Suggests endpoints like GET /todos, POST /todos, etc.]
You: "What about filtering and pagination?"
Copilot: [Extends the previous answer with query parameters]
You: "Generate the Express.js routes for this"
Copilot: [Provides complete implementation]
Learning and Exploration
Use Chat to learn new concepts:
"Explain the difference between:
- useMemo and useCallback in React
- When should I use each one?
- Show me examples where using the wrong one would cause issues"
Or explore technologies:
"I'm considering using Redis for caching in my Node.js app.
- What are the main use cases?
- How does it compare to in-memory caching?
- What are the gotchas I should know about?"
Effective Chat Prompts
Be Specific About Context
// Less effective:
"How do I fix this?"
// More effective:
"I'm getting a TypeScript error TS2345 on line 23 where I pass
a string to a function expecting a number. The string comes from
user input. What's the best way to handle this conversion safely?"
Include Relevant Code
"Given this interface:
interface Config {
apiUrl: string;
timeout: number;
retries?: number;
}
How do I create a function that merges a partial config with defaults?"
Ask for Alternatives
"Show me three different ways to implement a singleton pattern in TypeScript,
with pros and cons of each approach"
Chat Limitations to Remember
- Context window limits - Very long conversations may lose early context
- No file system access - Chat can't read files you haven't shared
- No execution - It can't run code to verify suggestions
- Knowledge cutoff - May not know about very recent library updates
- Potential hallucinations - May suggest non-existent APIs or methods
Summary
Copilot Chat transforms how you interact with code:
- Use
/explainto understand unfamiliar code - Use inline chat (
Ctrl+I) for quick refactoring - Ask for code reviews to catch bugs and security issues
- Discuss architecture for design guidance
- Build on conversations for complex, multi-step tasks
- Be specific in your questions for better answers
Combined with inline suggestions, Chat makes Copilot a comprehensive coding assistant that can help with everything from syntax questions to architectural decisions.
Next, you'll learn how to use Copilot specifically for writing tests and documentation.

