DEV Community

Gerald Hamilton Wicks
Gerald Hamilton Wicks

Posted on

5 Essential Flags to Enable on Your TypeScript Code

Introduction

TypeScript is a powerful tool that brings static typing to JavaScript, providing a robust foundation for building scalable and maintainable applications. To maximize the benefits of TypeScript, it's crucial to enable certain compiler options flags that enhance type safety and code quality. In this article, we'll explore five essential flags you should enable in your TypeScript projects and how they can help you write better code.

Initial Setup

In this article, we will cover the TypeScript flags: noImplicitAny, strictNullChecks, strictPropertyInitialization, noImplicitReturns, and noUnusedParameters. To enable each flag, you need to update your tsconfig.json file, setting these flags to true as shown in the example below:

{
  "compilerOptions": {
    // ...other configurations
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictPropertyInitialization": true,
    "noImplicitReturns": true,
    "noUnusedParameters": true
  }
}
Enter fullscreen mode Exit fullscreen mode

1. Avoid using 'any' type

  • Flag: noImplicitAny
  • Description: The noImplicitAny flag ensures that you explicitly declare types instead of defaulting to the any type. This enhances type safety by preventing untyped variables from creeping into your codebase.
  • Pro Tip: Instead of using any, leverage the unknown type. To check if a variable is of the type you want, use type guards. If you're unfamiliar with type guards, check out this article: Elevate Your TypeScript Skills with Type Guards. This practice enforces better type checks and reduces runtime errors.

When you enable noImplicitAny, TypeScript will issue an error whenever it would have inferred any:

function fn(s) {
  // Type Error: Parameter 's' implicitly has an 'any' type.
  console.log(s.subtr(3));
}
Enter fullscreen mode Exit fullscreen mode

2. Enable strict null checks

  • Flag: strictNullChecks
  • Description: Enabling strictNullChecks ensures that null and undefined are only assignable to their respective types. This prevents common pitfalls related to null values and improves code reliability.
  • Pro Tip: Use optional chaining (?.) and nullish coalescing (??) operators to handle null and undefined values gracefully.

Setting strictNullChecks to true will raise an error if you try to use a variable that could be null or undefined without a proper check:

declare const loggedInUsername: string;

const users = [
  { name: "Oby", age: 12 },
  { name: "Heera", age: 32 },
];

const loggedInUser = users.find((u) => u.name === loggedInUsername);
// Type Error: 'loggedInUser' is possibly 'undefined'.
console.log(loggedInUser.age);
Enter fullscreen mode Exit fullscreen mode

3. Enforce strict property initialization

  • Flag: strictPropertyInitialization
  • Description: The strictPropertyInitialization flag ensures that all class properties are initialized either in the constructor or with a default value. This helps catch uninitialized properties early in the development process.
  • Pro Tip: Use definite assignment assertions (!) when you're sure a property will be initialized by the time it's accessed.

When set to true, TypeScript will raise an error when a class property is declared but not set in the constructor:

class UserAccount {
  name: string;
  accountType = "user";
  // Type Error: Property 'email' has no initializer and is not definitely assigned in the constructor.
  email: string;

  constructor(name: string) {
    this.name = name;
    // Note that this.email is not set
  }
}
Enter fullscreen mode Exit fullscreen mode

4. Enable noImplicitReturns

  • Flag: noImplicitReturns
  • Description: The noImplicitReturns flag ensures that all code paths in a function return a value. This helps catch logical errors where a function might accidentally return undefined or no value at all.
  • Pro Tip: Review your functions to ensure they have consistent return statements, providing a clear and predictable flow of data.

When enabled, TypeScript will check all code paths in a function to ensure they return a value:

// Type Error: Function lacks ending return statement and return type does not include 'undefined'.
function lookupHeadphonesManufacturer(color: "blue" | "black"): string {
  if (color === "blue") {
    return "beats";
  } else {
    ("bose");
  }
}
Enter fullscreen mode Exit fullscreen mode

5. Enable noUnusedLocals and noUnusedParameters

  • Flags: noUnusedLocals, noUnusedParameters
  • Description: These flags help you maintain a clean codebase by reporting unused local variables and parameters. This reduces clutter and makes the code more readable.
  • Pro Tip: Regularly review and refactor your code to remove unused variables and parameters, keeping your codebase clean and efficient.

These flags will report errors for unused variables and parameters, helping you keep your code tidy:

// Type Error: 'modelID' is declared but its value is never read.
const createDefaultKeyboard = (modelID: number) => {
  const defaultModelID = 23;
  return { type: "keyboard", modelID: defaultModelID };
};
Enter fullscreen mode Exit fullscreen mode

Conclusion

Enabling these essential TypeScript flags not only enhances type safety but also promotes best practices and code maintainability. By leveraging TypeScript's powerful type system and compiler options, you can write more robust and reliable code, ultimately leading to a smoother development experience.

By incorporating these flags and best practices into your TypeScript projects, you'll be well on your way to writing cleaner, safer, and more maintainable code. And you, what are the flags that you use in your TypeScript code?

Top comments (0)