Search code examples
typescripttypedoc

Why am I getting TS2322 only under certain circumstances?


I am trying to generate HTML documentation on my TypeScript project using Typedoc.

In one of the many files, there is this bit of code:

public doSomething(val: number | undefined | null | string): string | undefined | null {
  if (val === null || val === undefined || typeof val === 'string') {
    return val;
  }
  ...

WebStorm shows no errors; in fact, hovering over val in the return statement shows me that val is assumed to be of type string | null | undefined.

Compilation (i.e. running the application with nx serve) works flawlessly, as well. And the class this bit of code is contained in is instantiated in the main view of the web application.

Yet, when I try to build Typedoc, it fails on that return statement, saying:

TS2322: Type 'string | number' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'.

Apparently, whatever Typedoc uses to analyze that source code does not have the same capabilities of resolving type assertions as what is used when building the runnable application - but why? Where could I check and what could I reconfigure to make this work?

Of course, I could change this one instance in the source code, but if we cannot trust Typedoc to work with the same source code as what our regular development environment uses, this gets really hard to handle with a time of > 100 people that constantly commit code and most of which do not specifically check Typedoc compatibility.


EDIT: The target of the module where this code is located was set to es2020, but switching to es2022 made no difference, neither to Typedoc nor to the build executed as a part of nx serve.

Even more strangely, if I copy and paste the same function elsewhere in the codebase, even Typedoc has no problems with compiling it there. There is a local typedoc.config.json file, but it only points to the general file and indicates the local entry points.


Solution

  • TypeDoc maintainer here.

    nx serve does not perform type checking at all. You can verify this by adding a trivial type error with parseInt(1) and compiling.

    Webstorm uses the compiler API sometimes. The team behind it decided that they could do a better job than TS in terms of type inference, which while sometimes helpful, means that in complex projects it frequently does not match what tsc will do, so it also cannot be relied on.

    TypeDoc relies on the TypeScript compiler API to perform type checking. It does not do any itself. This means that any TypeScript errors coming out of TypeDoc should be completely reproducible with npx tsc --noEmit --project path/to/tsconfig.typedoc.json. If this is not the case, and you're able to provide a reproduction, please open an issue as it is a bug in TypeDoc.

    It's impossible to say for sure what's going wrong here without a reproduction, but I suspect that you have other compiler errors which resulted in a cascading effect that caused this one. Unreachable code can produce errors like this.

    declare function bar(x: number): void;
    
    function foo(x: string | number) {
        if (true) {
            return x;
        }
        // Unreachable code detected.(7027)
        // Argument of type 'string | number' is not assignable to parameter of type 'number'.
        //  Type 'string' is not assignable to type 'number'.(2345)
        bar(x);
    }