TypeScript compiler replaces simple inferred types with random dependency imports

Viewed 301

We're seeing simple inferred types like string|number being replaced by types from dependencies in our output declaration files... so string|number turns into import("csstype").AnimationIterationCountPropert in our d.ts files.

This causes strange, out of context intellisense names, and can cause issues in monorepos if symlinked packages don't have access to the dependency the TS compiler decides to use.

Here's an example of a function that could return a string or a number:

    const myFunc = (test: boolean) => {
      let returnString = 'something';
      let returnNumber = 1234;
      // Returns either string or number
      return test ? returnString : returnNumber;
    };

TS Inferred type: If you check the VSCode tooltip, the type for this function is:

(method) myFunc(test: boolean): string | number

Compiled Declaration: Everything looks good so far. Let's use tsc to compile this. Here is the output in myFunc.d.ts:

myFunc(test: boolean): import("csstype").AnimationIterationCountProperty.

What?! My source file didn't even include csstype or make any mention to it. AnimationIterationCountProperty does happen to also share the type string|number, so I'm guessing the TS compiler is trying to re-use its type since it shares the same signature?

This causes 2 problems:

  1. The code consuming this library doesn't necessarily have csstype in its node_modules, which causes an error.

  2. In the consuming code, my intellisense when I mouse over myFunc says the return type is AnimationIterationCountProperty which makes no sense in the context. This function has nothing to do with CSS types.

Is this intended behavior from the TS compiler? Or is this some sort of bug? Thanks for any help.


Additional info:

  1. Typescript 3.6.3

  2. If I explictly type the function with the return type string|number, this doesn't happen. It outputs the expected type.

  3. Here is our tsconfig:

{
  "compilerOptions": {
    "module": "es6",
    "moduleResolution": "node",
    "noImplicitReturns": true,
    "incremental": true,
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "rootDir": "src",
    "outDir": "lib",
    "sourceMap": false,
    "strict": true,
    "importHelpers": true,
    "target": "es2017",
    "declaration": true,
    "baseUrl": "src",
    "jsx": "react"
  },
  "compileOnSave": true,
  "include": ["src/**/*"],
  "exclude": ["**/__tests__/**"]
}
1 Answers
Related