New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[node] Missing global URL and URLSearchParams typings #34960
Comments
Rewrite the global URL and the node URL such that they can declaration merge? IIRC if you write it as interface+namespace+value it should merge without dupe errors provided the types line up. |
The problem is that we need a class in the global namespace. And here the declaration merging doesn't seem to work (which is the underlying problem behind #25342). See this small repro. |
@weswigham Any news on this? Has the "class merging in the global namespace" any chance to be supported by TS? If no, should we go for a new "node-global-url" package as mentioned in the issue description above? |
Just got bit by this, came here to report and found that it's been open for a few months with no apparent movement. Isn't The Real Problem that projects shouldn't be including both |
@thw0rted - as mentioned, isomorphic code (libraries that can run in both the browser and node without changes) often uses both, even though that gives you the intersection and not the union of the environment, which would be more correct. |
Surely there's got to be a better way to do it than just polluting the global namespace of your X environment with the stuff that only Y provides, though, right? I have different sets of config files (npm / webpack / tsc / etc) for different environments, and can conditionally ignore certain files if they're only used in one or the other. If we don't already have a documented standard practice for writing isomorphic libraries without including conflicting baseline libraries, we certainly should. |
MyCoolLib needs access to browser APIs if it's running in a browser, and node APIs if it's running in node. Using both Unrleated, but ideally the published declaration files would not reference or declare a dependency on either, so users of the lib don't get polluted, but that's hard to do at the moment due to the lack of "internal" declaration files / declaration bundling. |
So if using both is "development friendly" then how should this issue be resolved? I feel like there was a similar conflict between some kind of Buffer (or ArrayBuffer, or similar?) a few years back, but I can't recall the specifics. Is there some way we could rename one of the offending types to e.g. NodeURL, such that it transpiles to the right name in the emitted code? |
Typescript for it's non-DOM included libs uses a pattern like: interface Foo {
// instance stuff
}
interface FooConstructor {
readonly prototype: Foo;
new (...): Foo;
// static stuff
}
declare var: FooConstructor; This pattern means you can merge the separate declarations, as interfaces merge, and the var will be referring the the same (merged) type in both declarations, even if they are different. |
Node.js 8 will soon be out of LTS. That means Node.js modules will start targeting Node.js 10 and use the |
An alternative that I just created for some universal* code is as follows: declare var URL: typeof globalThis extends { URL: infer URLCtor }
? URLCtor
: typeof import('url').URL; Note that this needs to be in every file in which *universal: libraries that can run in both the browser and node without changes. An alternative to using the term "isomorphic", which another commenter uses above; alas, I'm something of a pedant over the semantics of the word isomorphic |
Addendum: The circular type definition error can be overcome by adding some additional requirement to the type inference where only the DOM lib would suffice. For example, I found that this works, but is ugly, and for current uses, i'll be using the above in my universal libs that use declare global {
var URL: typeof globalThis extends {
Document: new () => { querySelectorAll: any };
URL: infer URLCtor;
}
? URLCtor
: typeof import('url').URL;
} |
- `dom` has been removed from `lib` in the root TypeScript config. Disabling a library when it’s not needed is much harder than adding one that’s missing and causes simple to the point error messages. - Packages that use browser typings, now explicitly specify the `dom` library. - Types from `@appsemble/sdk` that are used by `@appsemble/types`, have been moved into a new `src/types.ts` file, so `@appsemble/types` can import these without needing to use the `dom` library. This means its dependants can also use `@appsemble/types` without using `lib`. - Types in `@appsemble/utils` are now explicitly exported, because the TypeScript compiler started complaining about it. - Some typings have been slightly simplified. - NodeJS packages now need to explicitly define the globals `URL` and `URLSearchParams` due to DefinitelyTyped/DefinitelyTyped#34960
The workaround in DefinitelyTyped/DefinitelyTyped#34960 (comment) was used to provide type compatibility with NodeJS and the dom types.
Is there any news or progress on this? I keep having to import {URL} from 'url' just to satisfy TypeScript even though it's already in the global scope in my NodeJS app. |
Works around an upstream typing issues with URL, URLSearchParams. Without this, the broker's tests fail when a type for URLSearchParams can't be found. Looks like this might've broken as a side-effect of specifying ES2019 in tsconfig.base.json in f6254f8 ? Xref: DefinitelyTyped/DefinitelyTyped#34960
Works around an upstream typing issues with URL, URLSearchParams. Without this, the broker's tests fail when a type for URLSearchParams can't be found. Looks like this might've broken as a side-effect of specifying ES2019 in tsconfig.base.json in f6254f8 ? Xref: DefinitelyTyped/DefinitelyTyped#34960
…als by @antongolub * feat(node): declare URL and URLSearchParams as globals closes: #34960 * chore(node): simplify URL and URLSearchParams global definitions * docs(node): add @SInCE comments for URL and URLSearchParam globals * refactor(node): tweak up URL global type after tsc manual tests * docs(node): minor jsdoc improvements for global URL and URLSearchParams
Just to confirm, this new fix means that we no longer need to |
It's hard to say what will happen in the future. But here is what we have right now: we can use |
A combination of @types/node and typescript: 3.7.3 yields:
Is there a good workaround for this now? |
I'm afraid that only TS 3.8.2+ seems to be working. This is due to v3.7.3 lib/dom.generated.d.ts#L16087 declare var URLSearchParams: {
prototype: URLSearchParams;
new(init?: string[][] | Record<string, string> | string | URLSearchParams): URLSearchParams;
}; v3.8.2 lib/dom.generated.d.ts#L16136 declare var URLSearchParams: {
prototype: URLSearchParams;
new(init?: string[][] | Record<string, string> | string | URLSearchParams): URLSearchParams;
toString(): string;
}; Anyway, I'll try to fix it. UPD
var URLSearchParams: typeof globalThis extends { SpeechRecognitionError: infer SpeechRecognitionError } ?
// For TS <= 3.8.2 compatibility
// https://github.com/microsoft/TypeScript/compare/v3.7.3...v3.8.2#diff-dc0eab937d15e62545da3ed7b4f40ad6b24f15dd88fbc6ceda2bfb4ed8356eb0R15085
{
prototype: URLSearchParams;
new(init?: string[][] | Record<string, string> | string | URLSearchParams): URLSearchParams;
}: {
prototype: URLSearchParams;
new(init?: string[][] | Record<string, string> | string | URLSearchParams): URLSearchParams;
toString(): string;
}; |
Check out #25677 -- DT versioning is a pain and a half, and I don't think there's a great answer yet. That issue does link to some changes in the README, which gave us this section. For the version-specific fixes you're looking at, the typesVersions feature, which lets you specify different typings for different TS versions. I said in the thread I linked above, I'm not sure how that interacts with different directories for different major library versions (Node already has /v12, /v14, etc), but it "should" be possible to provide different types to different TS versions. (It's just likely to result in a lot of duplication...) |
I see three ways:
I really can't decide which is the less evil. |
… "webworker" by @antongolub * fix(node): make global ULR decl compatible with lib "webworker" relates #58277 #34960 * fix(node): improve global URL var type resolution * refactor(node): handle URLSeachParams var type collision in the same way as for URL * refactor(node): simplify type condition for global URL and URLSearchParams
…hParams as globals by @antongolub * feat(node): declare URL and URLSearchParams as globals closes: DefinitelyTyped#34960 * chore(node): simplify URL and URLSearchParams global definitions * docs(node): add @SInCE comments for URL and URLSearchParam globals * refactor(node): tweak up URL global type after tsc manual tests * docs(node): minor jsdoc improvements for global URL and URLSearchParams
…atible with lib "webworker" by @antongolub * fix(node): make global ULR decl compatible with lib "webworker" relates DefinitelyTyped#58277 DefinitelyTyped#34960 * fix(node): improve global URL var type resolution * refactor(node): handle URLSeachParams var type collision in the same way as for URL * refactor(node): simplify type condition for global URL and URLSearchParams
This is a follow-up issue of #25342 and #19799.
In #25269 the
URL
andURLSearchParams
classes have been added as globals because since Node.js 10.0 they are exposed as globals.Because
lib.dom.d.ts
also exposes them as globals, projects which referenced both,node
andlib.dom
, got "Duplicate identifier 'URL'" errors (see #25342). Therefore the globalURL
andURLSearchParams
has been removed again.This fix (actually a workaround for a missing declaration merging feature of TypeScript) now has the drawback that we cannot use the global
URL
class in Node.js-code (instead we need to import it from theurl
module). This is especially bad for universal modules which are supposed to work in the browser + node by just using the globalURL
(which works since Node.js 10).So I want to discuss solutions for this atm. unsupported scenario here. (Without having local declarations in consuming projects.)
One solution would be to support this scenario in TypeScript (allow - exactly same? - global class definitions in multiple declaration files). @weswigham Would this be possible?
A more straight-foward solution would be to create a new DT package (e.g.
node-global-url
or maybe betterwhatwg-global-url
) which can be installed additionally and selected by using e.g."types": ["node", "node-global-url"]
in atsconfig.json
for projects which face the mentioned scenario above.Any other ideas?
The text was updated successfully, but these errors were encountered: