0

I have a bunch of JavaScript scripts that I want to improve using JSDoc and TypeScript Typings

I need to be able to compile them absolutely independently so the code from one script doesn't mess up the typing system in the other script.

script1.d.ts
export {};

declare global {
    var myGlobalVariable: {
        property1: {
            childProperty1: string;
        }
    }
}
script2.d.ts
export {};

declare global {
    var myGlobalVariable: {
        property1: {
            childProperty2: string;
        }
    }
}
script1.js
/// <reference path="script1.d.ts" />

console.log(myGlobalVariable.property1.childProperty1);
script2.js
/// <reference path="script2.d.ts" />

console.log(myGlobalVariable.property1.childProperty2);
tsconfig.json
{
    "compilerOptions": {
        "allowJs": true,
        "checkJs": true,
        "noEmit": true,
        "isolatedModules": true
    },
    "include": [
        "*.js"
    ]
}

Executing

> tsc

I am getting the errors

script2.d.ts(4,9): error TS2403: Subsequent variable declarations must have the same type.  Variable 'myGlobalVariable' must be of type '{ property1: { childProperty1: string; }; }', but here has type '{ property1: { childProperty2: string; }; }'.
script2.js(3,40): error TS2551: Property 'childProperty2' does not exist on type '{ childProperty1: string; }'. Did you mean 'childProperty1'?

Is there a way to configure TypeScript to build my isolated modules indeed in an isolated way?

Additionally I prepared a gist with all those files mentioned above.

UPD

Also raised the same issue in the TypeScript repo

UPD2

To clarify confusions I will provide more context why do I need such architecture.

I am using Obsidian note-taking app with the Dataview plugin.

This plugin allows to execute custom JavaScript

```dataviewjs
await dv.view('script1');
```

which will invoke abovementioned script1.js

Internally Dataview executes script1.js by reading its content and evals it.

Naturally, script1.js and script2.js are executed and evaled independently and have no shared context.

mnaoumov
  • 2,146
  • 2
  • 22
  • 31
  • Put them in different projects with separate tsconfig files. Or do not use tsconfig at all but pass the file names explicitly to `tsc`. In any case, you'll need to run `tsc` separately for each, with different includes. – Bergi Aug 08 '23 at 22:52
  • @Bergi I am hoping there is a solution that can fit in my current project architecture – mnaoumov Aug 08 '23 at 22:56
  • This isn't isolating the globals, but you can certainly fix the type checking your by making the type of `property1` an interface. Therefore, it's declarations will be merged. – Aluan Haddad Aug 08 '23 at 22:58
  • @mnaoumov This doesn't make sense. You *have* two projects, otherwise the globals would collide if the scripts ran in the same environment. So: why? – Bergi Aug 08 '23 at 22:59
  • @Bergi Because `script1.js` and `script2.js` are used independently and executed at different times. Consider them as plugins invoked only when appropriate – mnaoumov Aug 08 '23 at 23:04
  • @AluanHaddad No, I don't want to merge the definitions. In the context when `script2.js` is invoked, the property `childProperty1` doesn't exist at all – mnaoumov Aug 08 '23 at 23:04
  • Honestly I don't understand what you're trying to do anymore. Module isolation applies to modules, not to scripts. Isolating your scripts isn't a thing if they contribute to the same application. Furthermore, declarations within modules which explicitly augment the global scope exist explicitly to escape the encapsulation of modules. – Aluan Haddad Aug 08 '23 at 23:08
  • 1
    @mnaoumov I hope your application makes sure never to load both plugins at once :-) Anyway, independent plugins sound very much like separate projects to me. – Bergi Aug 08 '23 at 23:08
  • @Bergi thanks for your questions, I provided an UPD to my post explaining better my use case – mnaoumov Aug 08 '23 at 23:15
  • 1
    "*Naturally, script1.js and script2.js are executed and evaled independently and have no shared context.*" - not sure how that comes naturally, what if you use both in a dataview on the same page? I don't know anything about obsidian-dataview, but the docs don't mention it (or anything about iframes or the like). Even if you tried it, I wouldn't take that behaviour as a given. – Bergi Aug 08 '23 at 23:23
  • Anyway, to stop complaining and be more constructive: take a look at [the `tsc` cli options](https://www.typescriptlang.org/docs/handbook/compiler-options.html). You can it on an individual file, without using a tsconfig.json; or you can use two separate tsconfig files (with different include paths) and point `tsc` at them. But as said before, you must run `tsc` multiple times, there's no way to do this in a single call. – Bergi Aug 08 '23 at 23:25
  • 1
    this is not possible at least logically basically in script1 you have `myGlobalVariable` of type X and script2 running alongside script1 which has `myGlobalVariable` as type Y. I mean a variable cannot represent 2 states at the same time (except in quantum physics) – Tachibana Shin Aug 09 '23 at 00:46
  • @TachibanaShin if you look at the title of my question, it makes more sense – mnaoumov Aug 09 '23 at 01:12
  • 1
    Does this answer your question? [how to setup a Typescript project with multiple source dirs and separate compile destinations?](https://stackoverflow.com/questions/68195354/how-to-setup-a-typescript-project-with-multiple-source-dirs-and-separate-compile) or [Preventing inappropriate imports and enforcing project hierarchy in Typescript](https://stackoverflow.com/q/61241866/8910547) – Inigo Aug 09 '23 at 05:15

0 Answers0