Optimizing Team Productivity: Key Front-End Coding Practices with TypeScript and React

suzuki0430

Atsushi Suzuki

Posted on March 18, 2024

Optimizing Team Productivity: Key Front-End Coding Practices with TypeScript and React

With the recent expansion of our development team, we found it crucial to establish a front-end coding convention aimed at preserving readability and maintainability. This article focuses primarily on practices within TypeScript and React. We hope this serves as a valuable resource for you.

Naming Conventions for Functions and Variables

CONSTANT_CASE

Global constants are named in all uppercase letters, with words separated by underscores.

const MAX_USERS = 5;
Enter fullscreen mode Exit fullscreen mode

UpperCamelCase

Classes, types, and type parameters follow the UpperCamelCase convention, starting with a capital letter.

class UserAccount {}
type UserType = { name: string; age: number; };
Enter fullscreen mode Exit fullscreen mode

lowerCamelCase

Variables, parameters, functions, methods, properties, and module aliases adhere to the lowerCamelCase convention, starting with a lowercase letter.

let userName: string = "John Doe";
function getUserInfo(userId: number) {...}
Enter fullscreen mode Exit fullscreen mode

Handling Proper Nouns

Proper nouns also follow the naming conventions, adapting to camelCase as appropriate.

  • URLPathUrlPath, urlPath
  • iOSDeviceIosDevice, iosDevice

Usage of Multiple Words

Names other than root App or basic components are constructed using multiple words to ensure clarity.

// Good
const TodoList = () => <div>...</div>;
type ShopCategory = "Grocery Store" | "Cafe" | "Italian Restaurant";
Enter fullscreen mode Exit fullscreen mode

Initials and Abbreviations

Project-specific abbreviations that might not be immediately clear to new team members should be avoided.

// Good
let backendManager = new BackendManager();
Enter fullscreen mode Exit fullscreen mode

Comments

Avoid Stating the Obvious

Omit comments when the name itself makes the intent clear.

Explain the "Why," Not the "What"

Comments should clarify why a piece of code is written, not what it does.

// WHY: To ensure the user is of legal age
if (user.age >= 18) {...}
Enter fullscreen mode Exit fullscreen mode

Marking Code Imperfections

Use TODO, NOTE, FIXME to highlight areas needing improvement or attention.

// TODO: Improve performance
// FIXME: Incomplete error handling
Enter fullscreen mode Exit fullscreen mode

TypeScript-Specific Guidelines

Favor named export Over default export

Named exports enhance code clarity and reusability.

// Good
export const getUser = () => {...};
Enter fullscreen mode Exit fullscreen mode

Prefer type Over interface

type is favored for its flexibility and the ease with which its contents can be inspected in VS Code.

type User = {
  name: string;
  age: number;
};
Enter fullscreen mode Exit fullscreen mode

Use Union Types Instead of enum

Union Types are preferred for their direct impact on the compiled code, utilizing TypeScript's type advantages without runtime overhead.

type Role = "admin" | "user" | "guest";
Enter fullscreen mode Exit fullscreen mode

Prioritize undefined Over null

Using undefined over null simplifies the TypeScript type system and is generally recommended.

let user: User | undefined = undefined;
Enter fullscreen mode Exit fullscreen mode

Components

Append Basic Component Names Last

Names end with basic component descriptors (Container, View, Button, etc.) to clarify their roles.

const UserProfileContainer = () => <div>...</div>;
Enter fullscreen mode Exit fullscreen mode

Order of Words

Start with the most general word and end with descriptive modifiers for clear naming.

// Good
const SearchResultList = () => <div>...</div>;
Enter fullscreen mode Exit fullscreen mode

Tightly Coupled Components

Names of components that are closely related should reflect their association, often by prefixing with the parent component's name.

const TodoList = () => <ul>...</ul>;
const TodoListItem = () => <li>...</li>;
Enter fullscreen mode Exit fullscreen mode

Typing Props

Clearly define expected properties through type annotations to maintain component contract integrity.

type Props = {
  onClick: () => void;
  title: string;
};
const Button: React.FC<Props> = ({ onClick, title }) => (
  <button onClick={onClick}>{title}</button>
);
Enter fullscreen mode Exit fullscreen mode

Avoid the Spread Syntax in Props

To prevent unnecessary properties from being passed, use the spread syntax cautiously.

// Good
const userDetails = { name: "John", age: 30 };
<UserProfile {...userDetails} />
Enter fullscreen mode Exit fullscreen mode

Writing Conditional Statements

Always use {} to wrap if statements

Even when the statement can be written in one line, wrapping it in braces enhances readability.

// Not recommended
if (condition) return;

// Recommended
if (condition) {
  return;
}
Enter fullscreen mode Exit fullscreen mode

Comparing Boolean Values

Prefer comparing directly to true

Explicit comparison makes the intention of your code clearer.

// Not recommended
if (!disabled) {
  doSomething();
}

// Recommended
if (enabled) {
  doSomething();
}
Enter fullscreen mode Exit fullscreen mode

For boolean variables, use prefixes like is, has, can, should to clarify their type. However, it's common practice not to apply this rule to component props.

// Not recommended
<RoundButton isDisabled={true} />

// Recommended
<RoundButton disabled />
Enter fullscreen mode Exit fullscreen mode

Using Ternary Operators

Avoid ternary operators when not using the return value

// Not recommended
condition ? doSomething() : doSomethingElse();

// Recommended
if (condition) {
  doSomething();
} else {
  doSomethingElse();
}
Enter fullscreen mode Exit fullscreen mode

Choosing Between Switch Statements and Map Objects

Consider Map objects for managing key-value based logic

Maps can be particularly useful for handling cases based on key-value pairs.

// Example using switch statement
switch (type) {
  case "walk":
  case "bicycle":
    return "Back Load";
  case "motorcycle":
  case "car":
    return "Main Load";
}

// Example using a Map object
const vehicleLoadMap = {
  walk: "Back Load",
  bicycle: "Back Load",
  motorcycle: "Main Load",
  car: "Main Load"
};

return vehicleLoadMap[type];
Enter fullscreen mode Exit fullscreen mode

Defining Event Handlers

Define event handlers outside of component body

This practice keeps the component body clean and improves readability.

Strategies for Memoization

Apply memoization judiciously

  • Consider wrapping frequently re-rendered or seldom-changing props components with React.memo.
  • Memoization can enhance performance but may introduce overhead if misused, so choose your scenarios wisely.

Utilizing String Literal Types

Prefer string literal types over enums for type safety without redundancy

This approach ensures type safety while avoiding unnecessary code.

// Not recommended
const ALERT_TYPE = {
  INFO: "INFO",
  SUCCESS: "SUCCESS",
  WARNING: "WARNING",
} as const;

// Recommended
type AlertType = "INFO" | "SUCCESS" | "WARNING";
Enter fullscreen mode Exit fullscreen mode

Applying CSS

Use clsx to manage class names based on conditions

// Example using `clsx`
import clsx from 'clsx';

<div className={clsx([styles.someStyle, isFoo && styles.fooStyle])}>
  Text here
</div>
Enter fullscreen mode Exit fullscreen mode

Specifying Values for Props

Follow a unified naming convention for passing props

This ensures the purpose of props is clear, facilitating data passing between components.

// Naming example for passing a collection
const TodoList: React.FC<{ items: TodoItem[] }> = ({ items }) => {...};

// Naming example for passing a single object
const TodoItemDetail: React.FC<{ item: TodoItem }> = ({ item }) => {...};
Enter fullscreen mode Exit fullscreen mode

Final Thoughts

This guideline aims to uphold consistency and improve efficiency in front-end development using TypeScript and React. Adjustments may be necessary depending on project or team specifics, but striving for best practices is paramount. Through these conventions, we hope to enhance the readability and maintainability of our projects, facilitating smoother development processes and collaborations within the team.

💖 💪 🙅 🚩
suzuki0430
Atsushi Suzuki

Posted on March 18, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related