Type definitions

This could probably be generated during npm publish (in case it is ever shipped with the code). Otherwise it should probably go into the typed typings repo on github so everyone can find them.

Have a look at this link. If we can change the package.json then this should be enough. In case Marijn decides to publish the d.ts files alongside the npm package then even having the .d.ts file next to the original JS file should be enough.

I have done some digging on the topic of .d.ts generation - there seems to be a library written in F# that generates definition files from XML (not really what we need).

The best would probably be to use the TypeScript Compiler API (e.g. build an AST from JavaScript+Annotations and then compile a ts/d.ts file from it. I’ve read about some libraries that try to do this for flow but again, did not find anything that could be adapted right away.

Your template approach seems to be the most straight forward and quickest to a solution.

Thanks for looking into that! We also tried to generate definitions for prosemirror. We attempted doing the following approach:

  • runing lebab to convert src/**/*.js to es6 on a separate folder
  • renaming all ‘.js’ to '.ts’
  • running tsc(typescript compiler) with some sane default settings to generate definitions
  • running dts-bundle(type definition bundler) to merge all the .d.ts files into a single one with the declared modules.

We got an almost perfect representation. We however had to clean by hand, the problems we found were:

  • Not able to generate definitions for this.foo=bar type of assignments inside the constructor
  • Not able to generate definitions for modules that used the copyObj() to mingle the exports

Our approach was to have a CI build that will attempt to check compatibility with latest prosemirror and this type definitions file and fix by hand from there on.

Would be great if prosemirror itself could export its definitions files. Otherwise we could add the current definitions file that we have to either definitelyTyped or a typings repository so that we could leverage from the community contribution.

Would anyone be so kind to share their typings? Preferably via a public github repo, so that it can be easily installed via typings :wink:

I don’t even need to have a .d.ts that is feature-complete or on a par with the latest releases, just enough to start playing with ProseMirror in TypeScript and not having the IDE complain about the imports and missing modules…

HI @Mobiletainment will talk to the team here and see if we can open it up to a public repo

1 Like

Hello @mitermayer, thank you very much for your help. Did you already have a chance to clarify if you’re able to share your typings?

Kind regards, David

In the meanwhile, I found this npm package with the type definitions: atlassian-prosemirror-type-definitions

Thumbs up and thank you!

Yeah @Mobiletainment, forgot to mention, we published the type definitions to NPM, we have not moved the repo yet to a public repository to allow contributions but we should be doing that soon. Feel free to use our npm package https://www.npmjs.com/package/atlassian-prosemirror-type-definitions however there are still chances that some definitions are broken, we are fixing as we go during our development. Will talk to the team this week to see if we can open the repository to the public to allow external contributions

I’ve also been working on a prosemirror.d.ts file for the latest version, and have something that is mostly working (though not complete, it covers all the parts of pm we’re interacting with and then some). Happy to share it, but also trying to make it a bit more finished first.

Hi @kookster, have you made any progress in generating the type definitions? If yes could you please share them?

Here’s what we’re using, have a look:

I suppose I should put them in the typings registry (https://github.com/DefinitelyTyped/DefinitelyTyped or https://github.com/typings/registry), especially to make them easier for others to use. Let me know how these work for ya @davidka!

That’s great, thanks!

As I see there are some places (e.g. constructor’s) with type “any” although the type information is available:

  class Mark {
   constructor(type: any, attrs: any);
   type: MarkType;
   attrs: any;
   ...

How did you generate the file? From code comments? Maybe we can improve this a little before publishing to typing registry

I’m currently working on a project using ProseMirror with TypeScript. I’ve noticed that the bindings available through DefinitelyTyped are outdated (they describe version 0.18 of ProseMirror) and also inaccurate in some places.

Some of the inaccuracies can be fixed by improving the generator that takes the getdocs documentation and produces the type declarations:

  • API calls that may return null or undefined are marked with a ? in front of the return type (e.g. maybeChild(index: number) → ?Node) in the ProseMirror documentation. The TypeScript declarations currently lack this information (maybeChild(index: number): ProsemirrorNode). Using the null and undefined types introduced in TypeScript 2.0 we could give this function the more correct signature maybeChild(index: number): ProsemirrorNode | undefined | null. Looking at the implementation of maybeChild, we can see that maybeChild may return undefined, but does not return null. So the most accurate type would be maybeChild(index: number): ProsemirrorNode | undefined in this case. But this can’t be deduced from the getdocs annotations in their current form.
  • Types of the form Object<SomeType> that describe javascript objects whose values are of the type SomeType aren’t translated correctly. For example, the nodes member of the Schema class has the annotation nodes: Object; instead of the more accurate nodes: { [name: string]: NodeType };

Then there are some corrections that can only done manually:

  • The DOMOutputSpec interface described in prose in the documentation can be manually translated to a TypeScript definition:
   interface DOMOutputSpecArray {		    interface DOMOutputSpecArray {
      0: string,		      0: string,
      1?: DOMOutputSpec | 0 | { [attr: string]: string },		 +    1?: DOMOutputSpec | 0 | Object,
      2?: DOMOutputSpec | 0,		      2?: DOMOutputSpec | 0,
      3?: DOMOutputSpec | 0,		      3?: DOMOutputSpec | 0,
      4?: DOMOutputSpec | 0,		      4?: DOMOutputSpec | 0,
     5?: DOMOutputSpec | 0,		     5?: DOMOutputSpec | 0,
     6?: DOMOutputSpec | 0,		     6?: DOMOutputSpec | 0,
     7?: DOMOutputSpec | 0,		     7?: DOMOutputSpec | 0,
     8?: DOMOutputSpec | 0,		     8?: DOMOutputSpec | 0,
     9?: DOMOutputSpec | 0		     9?: DOMOutputSpec | 0
   }		   }
   type DOMOutputSpec		   type DOMOutputSpec
       = string		       = string
       | Node		       | Node
       | DOMOutputSpecArray		       | DOMOutputSpecArray
  • Many methods of Transform (e.g. clearMarkup(from: number, to: number) → Transform) return the object itself, so you can build transforms by chaining calls together. When you call these methods on the child class Transaction, you will obviously get a Transaction back. But the TypeScript signature is clearMarkup(from: number, to: number): Transform, so TypeScript thinks that you only get a transform back. Using polymorphic this types, a type introduced for chainable APIs, we can give clearMarkup the declaration clearMarkup(from: number, to: number): this. Then TypeScript will be able to infer that someTransaction.clearMarkup(from, to) is still a transaction, not only a transform.

I would like to help bringing the type declarations up to date and fixing these inaccuracies. The bindings currently published on DefinitelyTyped to to have been generated using [davidka/buildtypedefs (https://github.com/davidka/buildtypedefs). Is that correct, @davidka? (Are there any instructions on how to produce the type definitions using your tool somewhere?) I think that we should fix the first group of inaccuracies in the generator, rerun the translator on the current version of ProseMirror and then check the generated type declarations manually and fix/enhance inaccurate ones.

Maybe we can add some option to the generator that causes it to use handwritten definitions (exporting them from some .d.ts file) instead of generating its own for selected interfaces/types. That way, we could save ourselves the effort of having to manually edit some auto-generated file every time there is a new release of ProseMirror. On the other hand @marijn has said that there won’t be any significant API changes at least before 1.0, so maybe it is less effort to just keep them up to date manually.

The 0.18 types at DefinitelyTyped are working well for getting started. I’ll probably keep using them, because they cut down on trial-and-error while developing.

I’m working on updating the types on DefinitelyTyped based on your work @timjb. https://github.com/DefinitelyTyped/DefinitelyTyped/pulls/bradleyayers

I’m using https://github.com/bradleyayers/generate-prosemirror-types as a bit of scaffolding to streamline the process.

I’ve raised some issues that overlap with some of the issues you’ve described, and will have a go at fixing them.

I’m doing a combination of using getdocs2ts (forked from your refactor branch of buildtypedefs) and manually making changes so that we can have types in the short term, while improve the tool in the longer term.

Hey @bradleyayers! I would like to be able to generate the type signatures fully automatically in the future, without manual editing required. Therefore it would be good to have a list of things that you have fixed manually while working on the definitions for 0.21, so we can work on automating them. If there is incorrect documentation (I have found some while working on this), it’s best to fix it upstream. I also want to make it possible to have the generator use custom definitions for some declarations/functions/etc. This way we could use the custom interface declaration for DOMOutputSpec for example.

1 Like

Sounds great! I’ve been recording the manual tweaks in the github issues on https://github.com/bradleyayers/getdocs2ts, there’s some missing like the “polymorphic this types” that you described, so feel free to raise those.

1 Like

@timjb @bradleyayers Great Job! My initial idea was to provide the type-generator to @marijnso so he can include this as an additional build step and include the typings with each release of prosemirror. To provide the *.d.ts files with prosemirror packages itself would remove the necessity to update it each time on DefinitelyTyped

https://github.com/DefinitelyTyped/DefinitelyTyped/pull/16981 has been merged, so hopefully we’ll have some 0.21 types out on NPM soon. No doubt there’ll probably be some refinement over time, but it’s a great step forward!

1 Like

If we want to make some changes, should we do them on definitelytyped directly? How does it work to keep track of the changes if the types are automatically generated?

For example, I’d like to add a type for (state: EditorState, dispatch?: (tr: Transaction) => void): boolean; in prosemirror-commands rather than repeating that everywhere.