Skip to content
This repository was archived by the owner on Jan 19, 2019. It is now read-only.
This repository was archived by the owner on Jan 19, 2019. It is now read-only.

Discussion: Extending core ESLint rules to "just work" with TS-specific nodes #77

Closed
@JamesHenry

Description

@JamesHenry

In agreement with @nzakas, I wanted to start a discussion here which summarises the findings so far on which core ESLint rules currently have issues with TypeScript-specific concepts, such as interfaces and decorators.

We do have a few options open to us with regards to making this all work (and the eslint-plugin-typescript plugin will still have its place regardless), but we are in agreement that it would be awesome if we did not have to duplicate any existing rules where all we are trying to do is match the same functionality as on standard JS nodes.

I have been running all of the core rules over a large TypeScript codebase (definitely not an exhaustive use of TypeScript features in there, but it's a great start) and noted the following, some of which is fairly subjective:


Rule: camelcase

We have the ability to control whether or not camelcase will apply to object properties, e.g.

"camelcase": ["error", { "properties": "never" }]

Opinion: We should be able to do this for TypeScript interfaces properties too


Rule: keyword-spacing

We can enforce spaces before and after keywords like so:

"keyword-spacing": ["error", { "before": true, "after": true }]

Opinion: We should be able to make type "casting" exempt from this in some way

E.g. I had this example:

<models.ICreativeTemplate>this.currentCreative.template

...where I would not want to put a space between the > and this keyword, but the rule naturally wants me to.


Rule: no-undef

With TypeScript, we are supporting class properties and interfaces. These are both causing false negatives with no-undef:

class A {
  foo = true
}

/* ESLint:
error, 'foo' is not defined
interface MyInterface {
  bar: string,
  baz: number
}

/* ESLint:
error, 'MyInterface' is not defined
error, 'bar' is not defined
error, 'baz' is not defined

It is very likely there are more TypeScript features that will cause the same, but currently those two are so noisy in my codebase that it is not worth investigating further.

This was also reported here: #75


Rule: no-used-vars

There are a couple of things causing false negatives with no-unused-vars:

(1) Class properties created via the constructor, and then later used in a method

class SomeClass {
    constructor(
        private foo: string
    ) {}
    someMethod() {
        return this.foo
    }
}

/* ESLint:
error, 'foo' is defined but never used

(2) Decorators

import { Injectable } from 'foo-framework'

@Injectable()
class Service {}

/* ESLint:
error, 'Injectable' is defined but never used

This was also reported here: #55


Rule: no-useless-constructor

Using the same class property assignment within a constructor example from above, we will also get a false negative on no-useless-constructor

class SomeClass {
    constructor(
        private foo: string
    ) {}
    someMethod() {
        return this.foo
    }
}

/* ESLint:
error, Useless constructor

Rule: space-infix-ops

This rule is basically unusable, given the type annotation syntax :


Rule: semi

It was pointed out here #61 (comment) that TypeScript-only statements will currently not be detectable as needing a semi-colon.

E.g.

"semi": ["error", "always"]
type Result<T> = Success<T> | Failure

/* ESLint:
(No error reported, but should point out missing semi-colon)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions