Description
I'm not sure if this feature is currently supported, or even whether the whole chain of features have been enabled to make this workflow work, but at the lowest level how would one compare two definitions (1.d.ts
and 2.d.ts
) and check if they're compatible? On top of this, would it be possible to access the definitions for a JavaScript library?
Reasoning: It'd be great to be able to type existing JavaScript libraries, but the biggest thing hindering third-parties is being able to integrate the workflow with CI. One way to improve this workflow would be with the --allowJs
flag on the library itself to generate one definition, then comparing it to the user-written definition. Having the declarations flag work with --allowJs
would also allow users to get started writing definitions 10x faster - just run tsc entry.js --allowJs --declaration --out definitions
and improve the types little by little.
Activity
basarat commentedon Mar 16, 2016
Just compile:
I haven't tested but should work 🌹
blakeembrey commentedon Mar 16, 2016
@basarat Interesting hack. I guess I'd have to generate this file, assuming it works, to do the test. The only outstanding piece is
allowJs
and declarations then.mhegazy commentedon Mar 16, 2016
allowJs
with--declaration
should be easy to enable. the emitter needs to be hardened to handle missing types, something it does not expect today. we would accept a PR for this if you are interested.The only restriction i see, there has to be a
--out
or--outDir
to make sure thata.d.t.s
is not dropped next toa.js
so that next compilation will not pick the outputa.d.ts
(as.d.ts
files are preferred to.js
files).mhegazy commentedon Mar 16, 2016
@blakeembrey can you log an issue to track allowing
--allowJs
with--declaration
?mhegazy commentedon Mar 16, 2016
As for the structural comparison, who is doing this? is it a command-line tool? do you expect it to be part of the compiler? how would it be surfaced to the user? what is the intended result?
if it is a separate tool, you can do what @basarat suggested.
blakeembrey commentedon Mar 16, 2016
Absolutely.
This is for writing type definitions with package authors. Definitely a CLI tool. I don't expect it to be part of the compiler. It can be part of @typings to validate a type definition on top of a JavaScript project. The intended result is that new, breaking API changes in JS have a chance of being caught by CI. For example, implementing typings for Express.js - references: expressjs/express#2818 and typings/typings#322.
--declaration
with--allowJs
#7546mhegazy commentedon Mar 16, 2016
Using the compiler API, we can definitely expose a new method on the TypeChecker to compare 2 types. so you would walk over the .d.ts file and the .js file simultaneously and get type for each export, and then compare their types.
blakeembrey commentedon Mar 16, 2016
@mhegazy That sounds like it'd be perfect 👍
mhegazy commentedon Mar 29, 2016
Feel free to file an issue for the API changes as needed.
blakeembrey commentedon Apr 27, 2016
@mhegazy I couldn't find an existing issue and it seems more realistic as this same request, but would the TypeScript compiler consider exposing a mode where it only type checks
.d.ts
(header files) against.js
(runtime files)? That's basically the request here, but without additional files being emitted. It'd allow people to adopt.d.ts
files into projects and keep them maintained and up-to-date properly, a massive win for the ecosystem.I was linked to a new project doing something like this, which renewed my interest in having a feature like this exposed (https://github.com/Raynos/jsig2).
mhegazy commentedon Apr 27, 2016
We will need a proposal for what that means to implement. also what are the scenarios you would use this mode. i would be inclined to say this is a tool that the compiler API can support. but I would like to understand the full picture first.
blakeembrey commentedon Apr 27, 2016
Anywhere we're working to merge
.d.ts
files into a JavaScript project. For example,moment
orexpress
. Right now, they have to guess changes to the.d.ts
files. Ideally, they could write the header files and keep the JavaScript files and runtsc
to catch type errors between them (like the linked project). This would guarantee that the people adopting writing definitions can keep them updated automatically (E.g. as part of CI). Without this, it'll need to be done manually and they'll need to check/remind every person that does a PR and changes the external.js
shape - which is a difficult task to do manually.mhegazy commentedon Apr 27, 2016
how far would this go, like there are JS dynamic constructs that can not be verified statically, e.g.
how would you check this against a .d.ts file?
blakeembrey commentedon Apr 27, 2016
I don't think there's any requirement to analyse that, but could it be allowed if there's extra exports in the
.d.ts
file that didn't match exports in the.js
file and TypeScript detects a dynamic export? That would be a requirement for things like the Express.js router.Basically, I think it'd be amazing if we can have a JavaScript/TypeScript file and create one
.d.ts
file that's part of the workflow and the.d.ts
(header file) is type checked against the body (the.js
file) as part of compilation. Maybe a flag to do this and libraries can use--noEmit
?mhegazy commentedon Apr 27, 2016
We should be able to create a .d.ts from a .js file. but i would think of this as a manual process, like you create the .d.ts to get you started. but then you would manually update the .d.ts file.
The issue with checking against a .d.ts file, is which is the truth? and how far are you willing to allow differences. and if it would still be useful after adding exceptions for dynamic content.
i think js code will be moving into more static shape at least for modules with the ES6 modules, so these dynamic cases might not be an issue in the future.
DanielRosenwasser commentedon Jan 26, 2017
You may want to take a look at TSEvolve which takes two
.js
files and an existing.d.ts
and can point out where changes have taken place. In principle, I don't see a reason why the comparison logic there couldn't be applied in this case. @webbiesdk, I believe you're involved in that project, right?webbiesdk commentedon Jan 26, 2017
Yes, I made that.
Yes, it could be used.
If used in a CI setting, it could list the changes between HEAD and the latest stable release.
Since it is based on an unsound type inference, it will list spurious changes, and it can therefore only be used as a help to whoever is updating the
.d.ts
file.Currently the project uses TypeScript 1.5 to parse the .d.ts files, and it doesn't work with NodeJS libraries. (Updating to TypeScript 2.1 shouldn't take long, but getting it to work with NodeJS could be quite a hassle).