Skip to main content

TypeScript ESLint

Introduction

When writing TypeScript code, having tools that help you maintain code quality and consistency is essential. One of the most powerful tools for this purpose is TypeScript ESLint. ESLint is a popular static code analysis tool that identifies and fixes problems in JavaScript code, and when combined with TypeScript, it provides an even more robust system for maintaining high-quality TypeScript code.

In this guide, we'll explore how to set up, configure, and effectively use ESLint with TypeScript to improve your development workflow and code quality.

What is TypeScript ESLint?

TypeScript ESLint is the combination of:

  1. ESLint: A highly configurable linting utility for JavaScript
  2. typescript-eslint: A package that enables ESLint to understand TypeScript code

This combination allows you to:

  • Catch syntax errors and potential bugs
  • Enforce consistent coding styles
  • Identify problematic patterns
  • Apply TypeScript-specific best practices
  • Integrate with your IDE for real-time feedback

Getting Started with TypeScript ESLint

Prerequisites

Before we begin, ensure you have:

  • Node.js and npm installed
  • A TypeScript project (or you're ready to create one)

Installation

Let's set up ESLint with TypeScript support:

bash
# Create a new project if you don't have one
mkdir ts-eslint-demo
cd ts-eslint-demo
npm init -y
npm install typescript --save-dev

# Install ESLint and TypeScript ESLint packages
npm install eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev

Configuration

Create a .eslintrc.js file in your project root:

javascript
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
plugins: [
'@typescript-eslint',
],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
],
rules: {
// Your custom rules here
}
};

This basic configuration:

  1. Specifies the TypeScript parser
  2. Adds the TypeScript ESLint plugin
  3. Extends the recommended ESLint and TypeScript ESLint rules

Key Concepts of TypeScript ESLint

1. Parser

The parser is responsible for converting your code into an Abstract Syntax Tree (AST) that ESLint can analyze:

javascript
// In .eslintrc.js
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
project: './tsconfig.json', // Points to your TypeScript configuration
},

2. Plugins

Plugins provide additional rules and functionality:

javascript
plugins: [
'@typescript-eslint',
// Other plugins you might use
],

3. Configurations (extends)

The extends property allows you to import sets of pre-defined rules:

javascript
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
],

4. Rules

Rules define specific coding standards you want to enforce:

javascript
rules: {
'@typescript-eslint/explicit-function-return-type': 'error',
'@typescript-eslint/no-explicit-any': 'error',
'semi': ['error', 'always'],
'quotes': ['error', 'single'],
},

Practical Examples

Let's look at how TypeScript ESLint can help you write better code.

Example 1: Type Safety

Consider this TypeScript code:

typescript
// Without TypeScript ESLint
function calculateTotal(items) {
let total = 0;
items.forEach(item => {
total += item.price * item.quantity;
});
return total;
}

const items = [
{ name: 'Shirt', price: 25, quantity: 2 },
{ name: 'Pants', price: 50, quantity: 1 }
];

const total = calculateTotal(items);

With TypeScript ESLint and appropriate rules, you would be prompted to add proper type annotations:

typescript
// With TypeScript ESLint
interface Item {
name: string;
price: number;
quantity: number;
}

function calculateTotal(items: Item[]): number {
let total = 0;
items.forEach(item => {
total += item.price * item.quantity;
});
return total;
}

const items: Item[] = [
{ name: 'Shirt', price: 25, quantity: 2 },
{ name: 'Pants', price: 50, quantity: 1 }
];

const total = calculateTotal(items);

ESLint would show errors for the first example if you have rules like @typescript-eslint/explicit-function-return-type enabled.

Example 2: Code Style Consistency

ESLint helps maintain consistent code style:

typescript
// Inconsistent code
const getUserData = async(userId:string)=>{
const user = await fetchUser(userId);
if(user){
return {
name: user.name,
email:user.email
}
}
return null
}

With ESLint rules for spacing, indentation, and semicolons, you would be guided to write:

typescript
// Consistent code after ESLint fixes
const getUserData = async (userId: string): Promise<UserData | null> => {
const user = await fetchUser(userId);
if (user) {
return {
name: user.name,
email: user.email
};
}
return null;
};

Example 3: Preventing Common Errors

ESLint can catch potential bugs:

typescript
// Potential bug
function processArray(array: string[]): void {
for (let i = 0; i <= array.length; i++) {
console.log(array[i].toUpperCase());
}
}

// Fixed version after ESLint warning
function processArray(array: string[]): void {
for (let i = 0; i < array.length; i++) {
console.log(array[i].toUpperCase());
}
}

In the first example, the loop condition i <= array.length would cause an error because arrays are zero-indexed, and ESLint could flag this with the appropriate rule.

Integrating with Your Development Workflow

Running ESLint from the Command Line

Add scripts to your package.json:

json
"scripts": {
"lint": "eslint . --ext .ts,.tsx",
"lint:fix": "eslint . --ext .ts,.tsx --fix"
}

Then run:

bash
npm run lint      # Check for issues
npm run lint:fix # Fix automatically fixable issues

VSCode Integration

For real-time linting in VSCode:

  1. Install the ESLint extension
  2. Add these settings to your .vscode/settings.json:
json
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"eslint.validate": ["javascript", "typescript"]
}

CI/CD Integration

Add ESLint checks to your continuous integration pipeline:

yaml
# Example GitHub Actions workflow
name: Lint

on: [push, pull_request]

jobs:
eslint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '14'
- run: npm ci
- run: npm run lint

Advanced Configuration

Using Shareable Configs

Shareable configs let you extend common rule sets:

bash
npm install eslint-config-airbnb-typescript --save-dev

Update your .eslintrc.js:

javascript
extends: [
'airbnb-typescript',
// Other configs...
],

Custom Rules

You can create project-specific rules:

javascript
rules: {
'@typescript-eslint/naming-convention': [
'error',
{
selector: 'interface',
format: ['PascalCase'],
prefix: ['I']
}
],
// Additional custom rules...
}

Ignoring Files

Create a .eslintignore file to exclude certain files or directories:

node_modules
dist
coverage
*.config.js

Common TypeScript ESLint Rules

Here are some useful TypeScript-specific rules:

RuleDescription
@typescript-eslint/explicit-function-return-typeRequires explicit return types on functions
@typescript-eslint/no-explicit-anyDisallows usage of the any type
@typescript-eslint/no-unused-varsPrevents variables being declared but not used
@typescript-eslint/no-non-null-assertionDisallows non-null assertions using the ! postfix operator
@typescript-eslint/await-thenableEnsures that await is only used with Promises

Troubleshooting Common Issues

ESLint Not Finding TypeScript Files

Make sure you're specifying the file extensions:

javascript
// In your ESLint command or configuration
"--ext .ts,.tsx"

Rules Not Working as Expected

Check that your configuration extends the correct rule sets and that your parser options are properly set:

javascript
parserOptions: {
project: './tsconfig.json',
tsconfigRootDir: __dirname,
},

Conflicts with Prettier

If you're also using Prettier, install the appropriate integration:

bash
npm install eslint-config-prettier eslint-plugin-prettier --save-dev

Then update your .eslintrc.js:

javascript
extends: [
// Other configs...
'plugin:prettier/recommended',
],

Summary

TypeScript ESLint is a powerful combination that enhances your TypeScript development experience by:

  1. Catching potential errors and bugs before runtime
  2. Enforcing consistent coding standards across your project
  3. Improving code readability and maintainability
  4. Providing real-time feedback in your IDE

By integrating ESLint into your TypeScript projects, you'll write cleaner, more robust code and catch issues early in the development process.

Additional Resources

Exercises

  1. Set up ESLint in a new TypeScript project and configure it with the recommended rules.
  2. Write a TypeScript function with intentional errors and use ESLint to identify and fix them.
  3. Create a custom ESLint rule that enforces a specific naming convention for your project.
  4. Configure ESLint to run automatically on your pre-commit git hooks using Husky.
  5. Experiment with different rule severity levels (error, warning, off) and observe how they affect your workflow.

By mastering TypeScript ESLint, you'll significantly improve your code quality and development efficiency!



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)