Takeshi Tokugawa YD
Takeshi Tokugawa YD

Reputation: 1001

"TS7030: Not all code paths return a value" vs. ESLint "no-undefined" and "no-useless return" conflict resolving

Target

I understand what ESLint is not the single source of truth, and moreover, could be oppositely customized, but in this question I want one of below result:

Conflict description

Below code is valid and working, but I have no-undefined ESLint rule violation:

@Component
export default class MyComponent extends Vue {

  public static getInstanceByReference(
    vueReference: Vue | Element | Array<Vue> | Array<Element>
  ): MyComponent | undefined {
    if (vueReference instanceof MyComponent) {
      return vueReference;
    }
    return undefined;
  }
}

If we delete undefined from return undefined, it will be no-useless-return rule violation:

@Component
export default class MyComponent extends Vue {

  public static getInstanceByReference(
    vueReference: Vue | Element | Array<Vue> | Array<Element>
  ): MyComponent | undefined {
    if (vueReference instanceof MyComponent) {
      return vueReference;
    }
    return;
  }
}

If we completely return useless from the view point of JavaScript last return, it will be the TypeScript error:

TS7030: Not all code paths return a value.
@Component
export default class MyComponent extends Vue {

  public static getInstanceByReference(
    vueReference: Vue | Element | Array<Vue> | Array<Element>
  ): MyComponent | undefined {
    if (vueReference instanceof MyComponent) {
      return vueReference;
    }
  }
}

If we change the return value signature to MyComponent | void, we get the no-invalid-void-type rule violation of @typescript-eslint.

Upvotes: 1

Views: 8146

Answers (1)

Brad Zacher
Brad Zacher

Reputation: 3243

The question I'd ask is "what is the goal of your code?"

If the goal is to signal an error/nothing state - then a "nullish" value is truly what you want. Given that your lint config (for whatever reason) bans the undefined value, then why not just use null?

 public static getInstanceByReference(
    vueReference: Vue | Element | Array<Vue> | Array<Element>
  ): MyComponent | null {
    if (vueReference instanceof MyComponent) {
      return vueReference;
    }
    return null;
  }

If you really want the undefined value without explicitly referencing undefined, then as per the no-undefined docs, you can just use the void operator:

 public static getInstanceByReference(
    vueReference: Vue | Element | Array<Vue> | Array<Element>
  ): MyComponent | undefined {
    if (vueReference instanceof MyComponent) {
      return vueReference;
    }
    return void 0;
  }

As an aside.

If we change the return value signature to MyComponent | void, we get the no-invalid-void-type rule violation of @typescript-eslint.

void should not be used in a union type. It's pretty a non-sensical type to say "this function returns something or returns absolutely nothing". It contradicts things and causes TS to act somewhat counter-intuitively (i.e. like disabling the missing return statement check).

This is why the no-invalid-void-type rule reports on MyComponent | void, and is no doubt the reason that your lint config has the rule turned on.

Upvotes: 2

Related Questions