Code Monkey home page Code Monkey logo

Comments (23)

blakeembrey avatar blakeembrey commented on June 30, 2024 1

Correct 👍 But this isn't just in the namespace, process is a variable that needs declaring at the top-level. There's a few fundamental limitations here. I'm not sure, but maybe we can propose a change in TypeScript to curb this because it definitely isn't the first time.

My initial thought is a TypeScript directive that'll ensure the file is always considered global or external. /cc @mhegazy @RyanCavanaugh How feasible would it be to allow import at the top-level if there was something to declare this file as a global declaration?

from env-node.

blakeembrey avatar blakeembrey commented on June 30, 2024

Seems like a good change. I think both the read and write streams should just be updated to the tty interfaces and not use streams directly.

from env-node.

felixfbecker avatar felixfbecker commented on June 30, 2024

They are totally different classes though. tty streams inherit from net.Socket

from env-node.

blakeembrey avatar blakeembrey commented on June 30, 2024

Ok, then what I should have said is to create new interfaces for this. I don't think you'd want a union here, TypeScript would still complain it doesn't exist until you do a type assertion then.

Edit: Sorry, you're right. Read the example wrong. You're definitely welcome to do a PR to quickly update as well 😄

from env-node.

blakeembrey avatar blakeembrey commented on June 30, 2024

Ok, so it turns out this is a real PITA to fix - any ideas? The issue is that the tty, net, stream, etc. are all modules by process it global. I wish there was a nice way in TypeScript to mix global with modules (like declare var process: Process from 'process' or something).

from env-node.

felixfbecker avatar felixfbecker commented on June 30, 2024

@blakeembrey shouldn't this work?

import {Process} from 'process';
declare const process: Process;

Assuming Process is an interface

from env-node.

blakeembrey avatar blakeembrey commented on June 30, 2024

No. You can't do that because the second you put import at the top-level, it makes the definition an external module format and not global. That's sadly just the rules TypeScript uses.

from env-node.

felixfbecker avatar felixfbecker commented on June 30, 2024

And the other way around?

declare namespace NodeJS {
  export interface Process {}
}  
declare module 'process' {
  type Process = NodeJS.Process;
  export {Process};
}

from env-node.

blakeembrey avatar blakeembrey commented on June 30, 2024

Yes, that's possible - but it requires moving all of stream, net, tty (just the pieces in use here) into the global NodeJS scope. It's actually the trick that's currently in use today, I just didn't want to make that change right away because it is a huge change.

from env-node.

felixfbecker avatar felixfbecker commented on June 30, 2024

And you cannot use import inside a namespace, right? I think that is the fundamental limitation here.

from env-node.

felixfbecker avatar felixfbecker commented on June 30, 2024

@blakeembrey It could be a new triple-slash directive.

Alternatively, it would also be enough if we could import inside namespaces. Then we could declare the globals by referencing the type from the namespace.

declare const process: NodeJS.Process;
declare namespace NodeJS {
  export {Process} from 'process';
}

from env-node.

RyanCavanaugh avatar RyanCavanaugh commented on June 30, 2024

I don't understand the question -- TypeScript always considers files as global or module depending on presence of top-level import / export declarations. You can use declare global { if you want something to go into the global scope from within a module file.

from env-node.

felixfbecker avatar felixfbecker commented on June 30, 2024

So we would change the whole declaration file to a module, but then put the majority of it inside declare global. Interesting! Might make the whole code way more structured because we can put stream stuff inside the actual 'stream' module, tty stuff inside 'tty', process inside 'process' etc.

from env-node.

felixfbecker avatar felixfbecker commented on June 30, 2024

@blakeembrey Could we even make individual files for the core node modules that are purely external? And then have one index that imports everything and declares the globals?

from env-node.

blakeembrey avatar blakeembrey commented on June 30, 2024

@RyanCavanaugh And that's exactly our problem. We need to share an interface globally declare var process: Process and within modules declare module "process". The pain here comes from the fact that some things have a very big module dependency chain to work (E.g. tty -> net -> stream) which all have to be moved global just to make process work. However, if we could import from a module into the global, this would be possible without polluting the global namespace with a ton of things that don't exist.

from env-node.

blakeembrey avatar blakeembrey commented on June 30, 2024

@felixfbecker Unfortunately that's not possible either, because we need to put declare module "stream" so TypeScript can recognise them. So either way, all the files would need to be global.

Using declare global may be possible with 2.0. Might be worth trying but I think the issue here is how TypeScript would treat this file. Since it's now external, I believe the global declaration would only take effect after the externalised node.d.ts module is imported. Is that correct @RyanCavanaugh?

from env-node.

felixfbecker avatar felixfbecker commented on June 30, 2024

@RyanCavanaugh I just tried out your suggestion, but it doesn't work:

declare module 'process' {
  export interface Process {}
}
import {Process} from 'process';
declare global {
    const process: Process; // Error: Module augmentation cannot introduce new names in the top level scope.
}

from env-node.

blakeembrey avatar blakeembrey commented on June 30, 2024

@felixfbecker I think the other issue with that is that import at the top-level makes the file external, which results in declare module "process" being an augmentation instead of a declaration of the original module. This, in turn, seems to result in errors with "process" not being found to import from to start with. At least on the latest nightly (which 2.0 does fix the module augmentation error you see) occurs with test.d.ts(4,23): error TS2307: Cannot find module 'process'..

from env-node.

felixfbecker avatar felixfbecker commented on June 30, 2024

That error can be circumvented by doing:

process.d.ts

export interface Process {}

node.d.ts

import {Process} from './process';
declare global {
    const process: Process; // Error: Module augmentation cannot introduce new names in the top level scope.
}

The error I mentioned remains though.

from env-node.

blakeembrey avatar blakeembrey commented on June 30, 2024

@felixfbecker Correct, but then there's no "process" global module declared, only a ./process external module. The error you mentioned is fixed in 2.0.

from env-node.

blakeembrey avatar blakeembrey commented on June 30, 2024

The only way around all this may be to combine module files, references and imports. E.g. Write declare "process" {} in it's own file, use it as a reference, then import { Process } from 'process' like your example above.

Edit: However, none of this fixes the concerns mentioned in #19 (comment) because having node.d.ts as an external module probably won't be used how we want it to be.

from env-node.

felixfbecker avatar felixfbecker commented on June 30, 2024

@blakeembrey Besides the error that is fixed in TS2.0, I found a solution:

process.d.ts

declare module 'process' {
  export interface Process {}
}

node.d.ts

/// <reference path="./process.d.ts" />
import {Process} from 'process';
declare global {
  declare const process: Process;
}

from env-node.

blakeembrey avatar blakeembrey commented on June 30, 2024

Yes, that's the proposal I suggested above. But it does not fix the concern I expressed (also above).

from env-node.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.