-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
Support d.ts files #1432
Comments
Deno does not resolve There is a whole ugly logic on |
@kitsonk I've been working on a reasonable and sane way to port node modules to deno, and it's unfortunate that this The issue I keep facing is that there's no way I know of to pair, merge, calculate the resolve of a module for instance Unless...
|
Why? I don't see why this would make any sense. It is a file is attesting it is compliant with the superset of syntax that TypeScript supports. Error in this file are errors. It would be dangerous and unsafe to run them.
There is no such thing.
It should. Could you provide an example where it doesn't? |
I've been thinking about writing stuff that would interop with standard JS, and I feel like it would be very annoying (long term especially) to be forced to not use .d.ts files. My main concern would be with how some JS is written, in that older styles tend to use more implicit mixins (this is a pattern I personally don't like, but it exists). A primary example would be the AWS SDK, which is build in such a way that it would be very difficult to get reasonable type definitions implicitly, which would (if the SDK worked at all with deno) make the implicit typings nearly impossible to use. I do think that it would be worth writing deno libraries from scratch in TS to properly support the platform, but you can't expect everyone to have the time or patience to rewrite entire existing libraries just to allow proper typing. Being able to port from existing Node packages to a deno module would be invaluable, and supporting .d.ts would definitely help with that. The only solutions I can think of is to provide a similar system to how the // @ts-defs ./deno_modules/lodash.d.ts
import lodash from './deno_modules/lodash.js'
console.log(lodash.add('2', '2')) It keeps with the explicit style that deno is after, but would require a little bit of middleware in the compiler to support, but could be possible by clipping into the same logic that // @ts-defs https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/lodash/index.d.ts
import lodash from './deno_modules/lodash.js'
console.log(lodash.add('2', '2')) Allowing (some) compatibility with the DefinitelyTyped project. |
We should definitely support .d.ts files... maybe initially by just looking for sibling files in the same directory ? |
For initial support, that would work, but it shouldn't be a permanent thing, since it goes against the general design, I feel. We would also need to consider remote .d.ts files, do we try and resolve those? If so, that would require implementing a request check that borders on what we didn't want to do for source files. Plus, if it's going to be dropped for a better system in future, it feels unnecessary to do (so local only for now seems to be better). |
I don't think you will every be happy with the performance implications. We killed extensionless partly because of this. Just consider for a moment, you load a plain Some sort of comment pragma like @luvies suggest is about the only thing I can think of that would work cleanly, and follows the more explicit nature of doing this. 1:1 mapping of I would look to try to stay away from comment pragma like |
I see that, |
Good point - I hadn't considered that. I guess if a program is completely JS it should be able to avoid the check for d.ts and only in the situation where TS imports JS would it would look for the sibling d.ts file - that doesn't seem too bad? (I'm not against special comments - I actually think it's a very nice way to augment script behavior... but for minimalism's sake I will play the antagonist role and argue against it.) |
Just want to mention that typescript does implement something like this, special comments + imports as /// <reference path="..." /> Deno could implement using the XML spec as they've outlined, perhaps even a new Deno would need to support this anyway because https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html |
Triple slash could work, but it would have to still have the context of the import, since the normal reference directive loads the typings into the current file directly I believe, rather than how import does it (by selecting specific exports, default importing or namespace importing). To work properly, I think it would need something like /// <reference module="..." defs="..." /> so it could then relate which definition reference mapped to which import. That, or do nearly the same thing as the |
So if a main module is TypeScript and a file being imported is JavaScript, Deno will look for a sibling file with the same name, but the
The TypeScript team have started to avoid the |
Also, it might be a good idea to only search sibling directories on a local file system. |
I also don't think fetching d.ts automatically or introducing special type imports is a good idea. Kills the whole predictability and extension explicitness thing. I'd rather prefer modules merged with its types together. Since we're always dealing with ES exports, we can potentially create some tool which applies types from d.ts to the js files as JSDocs for example and publish as a separate typed package. |
The challenge is that many On the other hand, you bring up an interesting potential, that if we settled on the conventions of resolving the |
Just a thought. How about to look at source map analogy - sourceMappingURL? https://sourcemaps.info/spec.html Multiple javascript files could point to the same d.ts file and that would then be loaded only once. It should be responsibility of the js file owner to provide a correct d.ts file. So no magic would be necessary. |
@oldrich-s I think something like that is ideal. Can it be achieved with triple slash directives?
|
Yes it can but as @luvies mentions the default typescript behaviour would load the d.ts file globally and not as an ordinary import. Therefore it could make sense to follow the source map convention instead with eg Edit: actually you could support both scenarios as they do different things - regular import vs global import. |
I have been thinking about this a fair amount. Proposing the following solution, which I plan to start working on. The solution needs to have the following features:
So based on these constraints/requirements, I propose the following:
To make this work, I think this is what I need to build:
I believe then that TypeScript will simply utilise the resolved |
@kitsonk The solution you outlined seems reasonable.
Maybe I'm betraying my ignorance of typescript, but what about using
It would be good if this could be done as part of the checkJs compilation (i.e. actually look for it in the AST provided by TS). I suppose a regex across the file is probably not measurably slow tho - so that might work for a first pass. |
That would be covered by point 1:
The way we need to interpret the triple slash directive is different than the way
I thought about that, the biggest problem is that trivia (comments) are not part of the AST in TypeScript. You basically have visit the node and then query if there is trivia. Even then I would have concerns that we would have to reparse each file, because you don't get back the AST until the parse happens, which requires all imports to be resolved. So we would parse the AST, load additional |
Actually, when using triple‑slash directives in a module, they’re used for resolving imports. When they’re used in a script, they’re used for resolving UMD globals, which are defined on the The exception to this are non‑module triple‑slash directives which only define ambient types, which are then available in the module or script where they’re used. |
What about using something similar to typescript's resource directives, but something they don't use:
Are these in the AST? |
There are more directives than /// <deno-types path="./foo.d.ts" />
A quick check says no, they are like other trivia, related to the next nearest node, but that seems a bit strange... I need to do more research and see that while they may not be in the AST, if there is another API the surfaces up triple-slash directives. I suspect there must be. |
Actually I was wrong, they are in the AST, if they are "known" directives. Why I didn't see it before was using the suggested text, which doesn't get parsed. Also they aren't part of the AST, as they are attributes on the So basically, anything that doesn't comply with a supported directive just looks like a comment. Also, my previous concern about when the AST would be available, and the need to "refresh" after we really resolved to model. I think the best thing to do at this point is to ensure the code is properly abstracted out, so that if we can somehow get that information from the AST in the future we would just need to change a method or two, but utilise RegEx for now (using some form of triple slash directive). |
SGTM |
I have a simple example here it's a
.js
file paired with ad.ts
file and deno doesn't throw any type issues where typescript does.Typescript does throw an issue here when run within the
node
runtime.The text was updated successfully, but these errors were encountered: