| name | typescript-typing |
| description | Fix TypeScript type errors by updating interface definitions, not usage sites. Handles DeepSignal state typing patterns. Use when fixing TypeScript errors from lint:ts-types or when type errors are reported. |
TypeScript Typing Fix Strategy
Core Principle
Fix types at interface definitions, not at usage sites.
MUST NOT change runtime behaviour - fixes must be purely additive (types, renames, reordering) or structural (moving declarations). Do not add conditionals, change control flow, or alter logic to satisfy the linter.
Quick Start
- Read the error → Find the interface/type definition
- Fix at source → Update interface to match actual usage
- Use inference → Let TypeScript infer types for variables when possible
- Always specify return types → Functions must have explicit return types (required by linting)
- Avoid assertions → Don't use
as Type or ! - fix the underlying type
Common Problems & Solutions
Property Doesn't Exist
Fix at interface definition:
interface Channel {
id: string
}
const channel: Channel = { id: '1', name: 'General' }
interface Channel {
id: string
name: string
}
DeepSignal Type Mismatches
Direct property access works without casts - DeepSignal proxies unwrap automatically:
const unread = $s.chat.channels[channelId].unread
$s.chat.channels[channelId].unread += 1
$s.chat.channels[key] = { id: key, messages: [] }
const channels = $s.chat.channels as PyriteState['chat']['channels']
channels[key] = { id: key, messages: [] }
import type {RevertDeepSignal} from 'deepsignal'
const channels = Object.values($s.chat.channels as RevertDeepSignal<typeof $s.chat.channels>)
Unknown Types
Add type annotation at source or use assertion:
const user = $s.users.find(u => u.id === id)
user.mic = true
const user = $s.users.find(u => u.id === id) as User
Return Types
Functions must always have explicit return types (required by linting rules):
export function _events(): void {
events.on('disconnected', () => {})
}
export function currentGroup(): typeof $s.sfu.channel {
return { ...$s.sfu.channel, ...channelData }
}
export async function loadData(): Promise<void> {
await fetch('/api/data')
}
Note: While functions require explicit return types, prefer inference for variables and other type annotations when possible.
Unused Variables
Catch blocks: Use catch {} when error is unused
try {
await operation()
} catch (error) {
handleError()
}
try {
await operation()
} catch {
handleError()
}
Other variables: Remove entirely, don't prefix with _
function process(data: Data) {
const _unused = data.oldField
return data.newField
}
function process(data: Data) {
return data.newField
}
Anti-Patterns
❌ Don't:
- Add
if (x !== undefined) checks just for TypeScript
- Use
as any to silence errors
- Add type assertions everywhere instead of fixing interfaces
- Prefix unused variables with
_ - remove them or use catch {}
- Omit return types on functions (always required by linting rules)
- Use inline type imports (e.g.
as import('pkg').Type) - add proper import at top of file
✅ Do:
- Fix interface definitions to match actual usage
- Use type assertions only when TypeScript errors occur
- Try direct property access first (DeepSignal unwraps automatically)
- Always specify explicit return types on functions (required by linting)
- Prefer inference for variables and other type annotations when possible
- Use
catch {} for unused catch variables
- Remove unused variables entirely
- Use proper imports at top of file - never inline
import('pkg').Type in type assertions
Quick Reference
| Error | Solution |
|---|
Property 'X' doesn't exist | Add property to interface definition |
Type 'X' is not assignable to type 'Y' | Update interface to match usage |
| DeepSignal Record assignment error | const x = $s.record as State['record'] |
Object.values() on DeepSignal | Object.values(x as RevertDeepSignal<typeof x>) |
unknown type | Add type annotation or assertion |
| Missing return type | Always add explicit return type to functions |
| Unused catch variable | Use catch {} instead of catch (_error) |
| Unused variable | Remove entirely, don't prefix with _ |
| Inline import in assertion | Add import type {Type} from 'pkg' at top |