TypeScript: Strict Typing and Readability
Core Principles
- •Avoid
anyandunknown— Use precise, explicit types - •Never silence type errors — Don't use
as anyto make it compile - •Optimize for maintainability — Prefer clear code over clever types
- •Fail fast — Validate inputs immediately, don't use placeholders
Type Safety
Bad: Using any or unknown
typescript
function processData(data: any) {
return data.someProperty;
}
const result = apiCall() as any;
Good: Explicit types
typescript
interface DataStructure {
someProperty: string;
otherProperty: number;
}
function processData(data: DataStructure): string {
return data.someProperty;
}
interface ApiResponse {
status: number;
data: DataStructure;
}
const result: ApiResponse = await apiCall();
When You Think You Need any/unknown
Investigate and fix the root cause:
| Problem | Solution |
|---|---|
| Upstream types missing/incorrect | Add or fix them |
| Invalid usage or design | Correct the code |
| Third-party types wrong | Augment types or contribute a fix |
Last resort only: Use any/unknown when avoiding them requires disproportionate effort. Keep usage minimal and documented.
Type Assertions
Bad: Broad assertions
typescript
const value = (someFunction() as any).property; const data = response as unknown as MyType;
Good: Type guards and validation
typescript
function isMyType(value: unknown): value is MyType {
return (
typeof value === 'object' &&
value !== null &&
'expectedProperty' in value
);
}
const data = someFunction();
if (isMyType(data)) {
console.log(data.expectedProperty);
} else {
throw new Error('Invalid data structure');
}
Generic Types
Bad: Untyped generics
typescript
function transform(items: any[]) {
return items.map(item => item.value);
}
Good: Typed generics
typescript
interface HasValue<T> {
value: T;
}
function transform<T>(items: HasValue<T>[]): T[] {
return items.map(item => item.value);
}
Error Handling
Bad: Catching without typing
typescript
try {
await someOperation();
} catch (error) {
console.log(error.message); // error is any
}
Good: Typed error handling
typescript
try {
await someOperation();
} catch (error) {
if (error instanceof Error) {
console.log(error.message);
} else {
console.log('Unknown error occurred');
}
}
Verification
After TypeScript changes:
- •Run
tsc --noEmitto check for type errors - •Fix all type errors before considering work complete
- •Ensure all type assertions are justified and minimal