5.6 KiB
5.6 KiB
name, description
| name | description |
|---|---|
| avoiding-angle-bracket-assertions | Avoid angle-bracket type assertions (<Type>) and use 'as Type' syntax instead |
Avoiding Angle-Bracket Type Assertions
The angle-bracket type assertion syntax (<Type>value) is deprecated in TypeScript, especially in TSX files where it conflicts with JSX syntax.
Why Avoid <Type> Syntax
- JSX conflict: Incompatible with TSX files (React, Preact, etc.)
- Inconsistent syntax: Modern TypeScript uses
as Type - Reduced readability: Looks like generics or JSX
- Tooling issues: Some tools don't handle it well
Modern Alternative: as Type
Basic Replacement
Deprecated:
const value = <string>someValue;
const num = <number>input;
Modern:
const value = someValue as string;
const num = input as number;
With Complex Types
Deprecated:
const user = <User>jsonData;
const config = <AppConfig>settings;
Modern:
const user = jsonData as User;
const config = settings as AppConfig;
Better: Avoid Type Assertions Entirely
Type assertions bypass type checking and should be avoided when possible.
1. Use Type Guards Instead
Bad:
function processValue(value: unknown) {
const str = value as string;
return str.toUpperCase();
}
Good:
function processValue(value: unknown) {
if (typeof value === 'string') {
return value.toUpperCase();
}
throw new Error('Expected string');
}
2. Use Validation Functions
Bad:
const user = apiResponse as User;
Good:
function isUser(value: unknown): value is User {
return (
typeof value === 'object' &&
value !== null &&
'id' in value &&
'name' in value &&
typeof value.id === 'number' &&
typeof value.name === 'string'
);
}
const parsed = apiResponse;
if (isUser(parsed)) {
const user = parsed;
} else {
throw new Error('Invalid user data');
}
3. Use Validation Libraries
Best:
import { z } from 'zod';
const UserSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string().email(),
});
type User = z.infer<typeof UserSchema>;
const user = UserSchema.parse(apiResponse);
4. Improve Type Inference
Bad:
const element = document.getElementById('myId') as HTMLButtonElement;
Better:
const element = document.getElementById('myId');
if (element instanceof HTMLButtonElement) {
element.addEventListener('click', handler);
}
Or use querySelector with type inference:
const element = document.querySelector<HTMLButtonElement>('#myId');
if (element) {
element.addEventListener('click', handler);
}
5. Use Discriminated Unions
Bad:
function handleEvent(event: Event) {
const mouseEvent = event as MouseEvent;
console.log(mouseEvent.clientX);
}
Good:
type AppEvent =
| { type: 'mouse'; clientX: number; clientY: number }
| { type: 'keyboard'; key: string }
| { type: 'custom'; data: unknown };
function handleEvent(event: AppEvent) {
switch (event.type) {
case 'mouse':
console.log(event.clientX);
break;
case 'keyboard':
console.log(event.key);
break;
case 'custom':
console.log(event.data);
break;
}
}
TSX-Specific Issues
In TSX files, angle-bracket syntax causes syntax errors:
Will cause syntax error in TSX:
const Component = () => {
const value = <string>getData();
return <div>{value}</div>;
};
Must use as syntax:
const Component = () => {
const value = getData() as string;
return <div>{value}</div>;
};
Even better - validate properly:
const Component = () => {
const data = getData();
if (typeof data !== 'string') {
throw new Error('Expected string');
}
return <div>{data}</div>;
};
When Assertions Are Necessary
If you must use assertions (rare cases):
1. Use as const for Literal Types
const config = {
apiUrl: 'https://api.example.com',
timeout: 5000,
} as const;
2. Use as Type (Never <Type>)
const value = unknownValue as SomeType;
3. Document Why It's Safe
const element = document.getElementById('app-root') as HTMLDivElement;
Migration Strategy
-
Find all angle-bracket assertions:
grep -r '<[A-Z][a-zA-Z]*>' --include="*.ts" --include="*.tsx" -
Replace with
assyntax:<Type>value→value as Type
-
Review each assertion:
- Can it be replaced with a type guard?
- Can validation library be used?
- Is it truly necessary?
-
Enable linting:
{ "rules": { "@typescript-eslint/consistent-type-assertions": [ "error", { "assertionStyle": "as", "objectLiteralTypeAssertions": "never" } ] } }
ESLint Configuration
Enforce as syntax and discourage assertions:
{
"rules": {
"@typescript-eslint/consistent-type-assertions": [
"error",
{
"assertionStyle": "as",
"objectLiteralTypeAssertions": "never"
}
],
"@typescript-eslint/no-unnecessary-type-assertion": "error"
}
}
Summary
Never use angle-bracket syntax:
- Use
as Typewhen assertions are unavoidable - Prefer type guards over assertions
- Use validation libraries for external data
- Validate at runtime for safety
- Document why assertions are necessary
- Enable linting to enforce consistency