7

I was reading the typescript-eslint docs and I came into this section:

TypeScript and ESLint have similar purposes
This means that there will be cases where TypeScript actually solves a problem for us that we previously relied on ESLint for.

Having their definition in mind, one is a statically typed language and one is a tool that parses code and puts some assertions in order to make sure some rules & patterns are considered, which are totally different things. I wanted to know what examples can be given for the part ‘solves a problem for us that we previously relied on ESLint for’. Do these two things have anything in common? What are their similar purposes?

Lauren Yim
  • 12,700
  • 2
  • 32
  • 59
Amir Hedieh
  • 1,120
  • 1
  • 14
  • 28
  • I don't think either provide coverage as that's usually provided by testing libraries, like jest. – evolutionxbox Sep 30 '20 at 19:05
  • I always used ESLint for Javascript, but not really had much use inside a Typescript file. I assume ESLint for Typescript is more likely used for coding standards, rather than coding errors. Eg. some project might want you to make sure you use semi colons, others that you have 4 space indenting etc, all this are not really errors, but ESLint can be made to flag them. – Keith Sep 30 '20 at 19:09
  • 1
    TypeScript is statically typed only because it uses "a tool that parses code...to make sure some rules and patterns are considered". This means that when TypeScript is transpired back to JavaScript it is statically checked in a similar way to es-lint. – Randy Casburn Sep 30 '20 at 19:15
  • IN terms of coverage - check this out: https://www.npmjs.com/package/tslint-html-report – Randy Casburn Sep 30 '20 at 19:16
  • @Keith there are errors that can be caught too. Leaked promises for example ... – w08r Sep 30 '20 at 19:24
  • 1
    @wobr Yes, sorry didn't mean to imply it never picked up errors too. More that for me I've not found ESLint as important for Typescript as I did for Javascript. – Keith Sep 30 '20 at 19:27

1 Answers1

9

Because JavaScript is a dynamically typed language, programmers can more easily introduce subtle bugs and errors that fail at runtime compared to static languages with a compiler that picks up on common issues.

Take the following code for example:

console.log(someUndefinedVariable)

const constant = 0
constant = 3

const addOne = n => {
  if (typeof n !== 'nubmer') {
    throw new Error('n must be an number')
    console.log('This will never be executed')
  }
  if (n < 0) console.log('negative number')
  else return n + 1
}
console.log(addOne(-3) * 2)

const symbol = new Symbol()

This code will fail at runtime and also has some other issues that may lead to unexpected results.

Linters such as ESLint pick up on some of these issues with rules such as no-undef and no const-assign:

 1:13  error  'someUndefinedVariable' is not defined      no-undef
 4:1   error  'constant' is constant                      no-const-assign
 7:20  error  Invalid typeof comparison value             valid-typeof
 9:3   error  Unreachable code                            no-unreachable
16:20  error  `Symbol` cannot be called as a constructor  no-new-symbol

Similarly, TypeScript's compiler will also warn you about many of these issues:

Cannot find name 'someUndefinedVariable'.

Cannot assign to 'constant' because it is a constant.

This condition will always return 'true' since the types
'"string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"'
and '"nubmer"' have no overlap.

Unreachable code detected.

'new' expression, whose target lacks a construct signature, implicitly has an 'any' type.

In this sense, ESLint and TypeScript have the same goal: to prevent likely programmer errors by warning you beforehand. For these issues, you can turn off the respective ESLint rules and use the TypeScript compiler instead.


However, the most important feature about TypeScript is its addition of static types to JavaScript. By adding type annotations to addOne:

const addOne = (n: number): number => { /* ... */ }

TS tells us that Function lacks ending return statement and return type does not include 'undefined'. because the function will return undefined instead of a number if n is a negative number. The result of addOne(-3) * 2 would be NaN, instead of -4 like expected.

Another example, which ESLint would be completely fine with but fails at runtime:

const foo = 0
const bar = foo()
//          ~~~
// This expression is not callable.
//   Type 'Number' has no call signatures.

These are some of the many issues that TypeScript can help identify due to its type system.

On the other hand, linters including ESLint and the typescript-eslint plugin can enforce best practices such as using strict equality operators and correctly handling promises. They can also enforce stylistic conventions such as indentation, requiring or forbidding semicolons, or consistent type assertion styles.


TypeScript and ESLint have the similar goal of preventing programmer bugs and errors. However, due to its type system, TypeScript can pick up on more runtime and programming errors, whereas ESLint can enforce stylistic conventions and best practices.

Lauren Yim
  • 12,700
  • 2
  • 32
  • 59