0

0. Prequisitions

  • typescript@4.3.4
  • Editor: VSCode 1.15.7
  • OS: Ubuntu 20.04

➡➡➡ Minimalist reproduce repo in here

1. Project Structure

I create a minimalist TypeScript project whose structure looks like this:

.  // Project root directory ($PWD)
├── dist
│   └── main.js  // output file
├── Makefile
├── package.json
├── package-lock.json
├── src
│   ├── main.ts
│   └── types
│       └── window.d.ts  // ←extends some properties to `global.Window` 
└── tsconfig.json

2. Customize Interface global.Window

I extends some customized properties attached on built-in Window global interface:

// window.d.ts
export { }  // to solve TS2669, see https://stackoverflow.com/questions/57132428/augmentations-for-the-global-scope-can-only-be-directly-nested-in-external-modul

declare global {
  interface OurDefinedGlobalRuntimeEnv {
    /** Runtime value (Defined in preload.js)
    *   - `web`: Ordinary web browser.
    *   - `electron`: Electron renderer window.
    */
    BROWSER: 'electron' | 'web' | undefined
    SERVER_IP: string
    DEBUG: string
    NODE_ENV: node_env_t,
  }
  type node_env_t = 'production' | 'development'
  interface Window {
    __RUNTIME_ENV__: OurDefinedGlobalRuntimeEnv
  }
}

Then inject our self-defined object into window:

// main.ts
type inferPropType<T, K extends keyof T> = T[K]
const rtenv1: inferPropType<Window, '__RUNTIME_ENV__'> = {
  BROWSER: 'electron',
  NODE_ENV: process.env.NODE_ENV === 'development' ? 'development' : 'production',
  SERVER_IP: process.env.SERVER_IP || '',
  DEBUG: process.env.DEBUG || '',
  ENV_VAR: process.env,
}
const rtenv2: OurDefinedGlobalRuntimeEnv = rtenv1
window.__RUNTIME_ENV__ = rtenv1

3. VSCode IntelliSense & tsc

So far, VSCode's IntelliSense doesn't output any error or warning, and type can be inferred by IntelliSense correctly: VSCode can infer types defined in d.ts correctly

And run tsc with the root path of the project as $CWD:

cd PROJECT_ROOT_DIR
npx tsc --outDir ./dist/ --module commonjs ./src/*.ts

However, this will explode: Error output by tsc

4. Where The Problem Is?

After debugging for > 7 hours, I found tsc cannot detect *.d.ts when the file want to be compiled and *.d.ts are not in the same folder. That is to say, if move window.d.ts:

.
└── src
    ├── main.ts
    └── types
        └── window.d.ts

become this:

.
└── src
    ├── main.ts
    └── window.d.ts

Now tsc compilation passed:

npx tsc --outDir ./dist/ --module commonjs ./src/*.ts

5. Questions

  1. In TypeScript official document, it seems own-defined *.d.ts can be placed in any sub folder of the project?
  2. VSCode's IntelliSense can correctly load and infer the types defined in our *.d.ts and the extended global Window interface, so I guess I didn't wrote the definition file wrongly...right?

The types defined in our window.d.ts will be used by multiple entry files, in this case I should not copy this window.d.ts to multiple folders.

(NOTE: This is merely a minimalist project to reproduce the issue, so I only wrote one entry file main.ts. In real world, this is actually a large Electron project which contains other entries files like preload.js and electron_entry.js and a SPA entry bundled by Webpack...etc)

  1. Does tsc --outDir OUT_DIR SRC_FILE always ignores ${PWD}/tsconfig.json unless I use tsc --project ./tsconfig.json or just tsc (will compile everything according to tsconfig.json)? I wonder know if I can just build **on specific .ts file via tsc XXXX... directly ** WITHOUT create multiple tsconfig.json nor via webpack.

  2. Although I found use tsc (without any parameters) can compile successfully (it loads tsconfig.json implicitly), but I don't know how it succeeded nor which option in tsconfig.json made it successful... Even with params --baseUrl . --rootDir . --moduleResolution Node --module commonjs still cannot load window.d.ts. `

kuanyui
  • 782
  • 13
  • 23

2 Answers2

2

since it is not referenced anywhere under the root path, the compiler is not aware of the existence of the global declaration file so you need to pass its path in addition to the root path (tsc gets set of TypeScript files)

so in your scenario, following would work:

npx tsc --outDir ./dist/ --module commonjs ./src/*.ts ./src/types/window.d.ts.

0

The command your are running : npx tsc --outDir ./dist/ --module commonjs ./src/*.ts is wrong. Here you are asking TypeScript to *only compile files under src/*.ts.

Fix

Compile with tsconfig i.e. npx tsc -p ./tsconfig.json. Or even npx tsc as it will pickup tsconfig.json by default

PS I tested your project, its fine enter image description here

basarat
  • 261,912
  • 58
  • 460
  • 511
  • Sorry, I've mentioned this way in my original question but it's not what I want (because I have 3 entry files in real world... So hard to explain, I totally cannot understand the behavior of `tsc`....). At last, I finally give up and wrote a `webpack.config.js` contains multiple entries to build my project, now problem seems solved... – kuanyui Jun 25 '21 at 02:36