[ PROMPT_NODE_24809 ]
Typescript Standards
[ SKILL_DOCUMENTATION ]
# TypeScript Standards
TypeScript best practices for type safety and maintainability in React frontend code.
---
## Strict Mode
### Configuration
TypeScript strict mode is **enabled** in the project:
```json
// tsconfig.json
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true
}
}
```
**This means:**
- No implicit `any` types
- Null/undefined must be handled explicitly
- Type safety enforced
---
## No `any` Type
### The Rule
```typescript
// ❌ NEVER use any
function handleData(data: any) {
return data.something;
}
// ✅ Use specific types
interface MyData {
something: string;
}
function handleData(data: MyData) {
return data.something;
}
// ✅ Or use unknown for truly unknown data
function handleUnknown(data: unknown) {
if (typeof data === 'object' && data !== null && 'something' in data) {
return (data as MyData).something;
}
}
```
**If you truly don't know the type:**
- Use `unknown` (forces type checking)
- Use type guards to narrow
- Document why type is unknown
---
## Explicit Return Types
### Function Return Types
```typescript
// ✅ CORRECT - Explicit return type
function getUser(id: number): Promise {
return apiClient.get(`/users/${id}`);
}
function calculateTotal(items: Item[]): number {
return items.reduce((sum, item) => sum + item.price, 0);
}
// ❌ AVOID - Implicit return type (less clear)
function getUser(id: number) {
return apiClient.get(`/users/${id}`);
}
```
### Component Return Types
```typescript
// React.FC already provides return type (ReactElement)
export const MyComponent: React.FC = ({ prop }) => {
return
);
};
```
---
## Utility Types
### Partial
```typescript
// Make all properties optional
type UserUpdate = Partial;
function updateUser(id: number, updates: Partial) {
// updates can have any subset of User properties
}
```
### Pick
```typescript
// Select specific properties
type UserPreview = Pick;
const preview: UserPreview = {
id: 1,
name: 'John',
email: '[email protected]',
// Other User properties not allowed
};
```
### Omit
```typescript
// Exclude specific properties
type UserWithoutPassword = Omit;
const publicUser: UserWithoutPassword = {
id: 1,
name: 'John',
email: '[email protected]',
// password and passwordHash not allowed
};
```
### Required
```typescript
// Make all properties required
type RequiredConfig = Required; // All optional props become required
```
### Record
```typescript
// Type-safe object/map
const userMap: Record = {
'user1': { id: 1, name: 'John' },
'user2': { id: 2, name: 'Jane' },
};
// For styles
import type { SxProps, Theme } from '@mui/material';
const styles: Record<string, SxProps> = {
container: { p: 2 },
header: { mb: 1 },
};
```
---
## Type Guards
### Basic Type Guards
```typescript
function isUser(data: unknown): data is User {
return (
typeof data === 'object' &&
data !== null &&
'id' in data &&
'name' in data
);
}
// Usage
if (isUser(response)) {
console.log(response.name); // TypeScript knows it's User
}
```
### Discriminated Unions
```typescript
type LoadingState =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: Data }
| { status: 'error'; error: Error };
function Component({ state }: { state: LoadingState }) {
// TypeScript narrows type based on status
if (state.status === 'success') {
return ; // data available here
}
if (state.status === 'error') {
return ; // error available here
}
return ;
}
```
---
## Generic Types
### Generic Functions
```typescript
function getById(items: T[], id: number): T | undefined {
return items.find(item => (item as any).id === id);
}
// Usage with type inference
const users: User[] = [...];
const user = getById(users, 123); // Type: User | undefined
```
### Generic Components
```typescript
interface ListProps {
items: T[];
renderItem: (item: T) => React.ReactNode;
}
export function List({ items, renderItem }: ListProps): React.ReactElement {
return (
{prop}
;
};
// For custom hooks
function useMyData(id: number): { data: Data; isLoading: boolean } {
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
return { data: data!, isLoading };
}
```
---
## Type Imports
### Use 'type' Keyword
```typescript
// ✅ CORRECT - Explicitly mark as type import
import type { User } from '~types/user';
import type { Post } from '~types/post';
import type { SxProps, Theme } from '@mui/material';
// ❌ AVOID - Mixed value and type imports
import { User } from '~types/user'; // Unclear if type or value
```
**Benefits:**
- Clearly separates types from values
- Better tree-shaking
- Prevents circular dependencies
- TypeScript compiler optimization
---
## Component Prop Interfaces
### Interface Pattern
```typescript
/**
* Props for MyComponent
*/
interface MyComponentProps {
/** The user ID to display */
userId: number;
/** Optional callback when action completes */
onComplete?: () => void;
/** Display mode for the component */
mode?: 'view' | 'edit';
/** Additional CSS classes */
className?: string;
}
export const MyComponent: React.FC = ({
userId,
onComplete,
mode = 'view', // Default value
className,
}) => {
return ...
;
};
```
**Key Points:**
- Separate interface for props
- JSDoc comments for each prop
- Optional props use `?`
- Provide defaults in destructuring
### Props with Children
```typescript
interface ContainerProps {
children: React.ReactNode;
title: string;
}
// React.FC automatically includes children type, but be explicit
export const Container: React.FC = ({ children, title }) => {
return (
{title}
{children}
{items.map((item, index) => (
);
}
// Usage
<List
items={users}
renderItem={(user) => }
/>
```
---
## Type Assertions (Use Sparingly)
### When to Use
```typescript
// ✅ OK - When you know more than TypeScript
const element = document.getElementById('my-element') as HTMLInputElement;
const value = element.value;
// ✅ OK - API response that you've validated
const response = await api.getData();
const user = response.data as User; // You know the shape
```
### When NOT to Use
```typescript
// ❌ AVOID - Circumventing type safety
const data = getData() as any; // WRONG - defeats TypeScript
// ❌ AVOID - Unsafe assertion
const value = unknownValue as string; // Might not actually be string
```
---
## Null/Undefined Handling
### Optional Chaining
```typescript
// ✅ CORRECT
const name = user?.profile?.name;
// Equivalent to:
const name = user && user.profile && user.profile.name;
```
### Nullish Coalescing
```typescript
// ✅ CORRECT
const displayName = user?.name ?? 'Anonymous';
// Only uses default if null or undefined
// (Different from || which triggers on '', 0, false)
```
### Non-Null Assertion (Use Carefully)
```typescript
// ✅ OK - When you're certain value exists
const data = queryClient.getQueryData(['data'])!;
// ⚠️ CAREFUL - Only use when you KNOW it's not null
// Better to check explicitly:
const data = queryClient.getQueryData(['data']);
if (data) {
// Use data
}
```
---
## Summary
**TypeScript Checklist:**
- ✅ Strict mode enabled
- ✅ No `any` type (use `unknown` if needed)
- ✅ Explicit return types on functions
- ✅ Use `import type` for type imports
- ✅ JSDoc comments on prop interfaces
- ✅ Utility types (Partial, Pick, Omit, Required, Record)
- ✅ Type guards for narrowing
- ✅ Optional chaining and nullish coalescing
- ❌ Avoid type assertions unless necessary
**See Also:**
- [component-patterns.md](component-patterns.md) - Component typing
- [data-fetching.md](data-fetching.md) - API typing {renderItem(item)}
))}
Source: claude-code-templates (MIT). See About Us for full credits.