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?
ESLint is a JavaScript linter that you can use to lint either TypeScript or JavaScript code.
Linters have been around for ages - it all started back in 1978 apparently - but has now become a mainstay of modern JavaScript and TypeScript programming. Writing code without a linter is like writing an essay without using spell checker!
TSLint is an extensible static analysis tool that checks TypeScript code for readability, maintainability, and functionality errors. It is widely supported across modern editors & build systems and can be customized with your own lint rules, configurations, and formatters.
In the TypeScript 2019 Roadmap, the TypeScript core team explains that ESLint has a more performant architecture than TSLint and that they will only be focusing on ESLint when providing editor linting integration for TypeScript. For that reason, I would recommend using ESLint for linting TypeScript projects.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With