Code Review in TypeScript: What to Check and How to Give Feedback
\n\nCode review is not just a formality, but a powerful tool for improving code quality and sharing experience within a team. For beginner TypeScript developers, this process can seem complex and intimidating. In this article, we will break down what to pay attention to when reviewing TypeScript code and how to give feedback that is useful and constructive.
\n\n1. Why is Code Review Important for TypeScript?
\n\nTypeScript adds static typing to JavaScript, which already helps avoid many errors at the compilation stage. However, code review allows you to identify issues that the compiler cannot see: logical errors, unreadable code, incorrect use of types, or architectural flaws.
\n\nThe main goals of code review in TypeScript:
\n- \n
- Improving code quality — identifying bugs and potential issues before they reach production. \n
- Learning — beginner developers learn from the examples of more experienced colleagues. \n
- Consistency of style — maintaining a clean and understandable codebase. \n
- Security — checking for vulnerabilities and improper use of third-party libraries. \n
2. What to Check in TypeScript Code: Key Aspects
\n\nWhen reviewing TypeScript code, it's important to look not only at the logic but also at how the language's features are used. Here are the key points to check:
\n\n2.1. Typing and the Use of any
\n\nOne of the main goals of TypeScript is to eliminate any. If any appears in the code, it's a reason to ask: "Why isn't a specific type used here?"
// Bad: any erases all the benefits of TypeScript\nfunction processData(data: any) {\n return data.name.toUpperCase();\n}\n\n// Good: use an interface\ninterface User {\n name: string;\n age: number;\n}\n\nfunction processData(data: User): string {\n return data.name.toUpperCase();\n}\n\nThe exception is working with dynamic data, for example, when parsing JSON. In such cases, use unknown instead of any and check the type.
2.2. Correctness of Types and Interfaces
\n\nCheck that interfaces and types are not redundant and do not contradict each other. Ensure that the types correctly describe the data structure.
\n\n// Bad: redundant interface\ninterface User {\n name: string;\n age: number;\n email?: string;\n address?: string;\n phone?: string;\n // ... many more fields\n}\n\n// Good: break it down into smaller interfaces\ninterface User {\n name: string;\n age: number;\n contact: ContactInfo;\n}\n\ninterface ContactInfo {\n email?: string;\n phone?: string;\n}\n\n2.3. Error Handling and null/undefined
\n\nTypeScript helps avoid errors related to null and undefined, but only if the developer correctly uses optional types and checks.
// Bad: not checking for null\nfunction getUserName(user: User | null): string {\n return user.name; // Error! user could be null\n}\n\n// Good: use optional chaining and a check\nfunction getUserName(user: User | null): string {\n return user?.name ?? 'Anonymous';\n}\n\n2.4. Using Generics
\n\nGenerics allow you to write reusable code. Check if there is duplicated logic that could be generalized.
\n\n// Bad: duplicating functions\nfunction getStringArray(items: string[]): string[] { return items; }\nfunction getNumberArray(items: number[]): number[] { return items; }\n\n// Good: use a generic\nfunction getArray<T>(items: T[]): T[] {\n return items;\n}\n\n3. How to Give Feedback: Rules for Beginners
\n\nEven if you find many errors, it's important to present