-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
Generate official TypeScript type definitions #8878
Conversation
It's been a long requested feature for us to have official TypeScript type definitions. While the community has done a yeoman's job of manually supporting various efforts, the most recent incarnation of which is `@types/cesium`, the sheer scale and ever-evolving nature of Cesium's code base makes manual maintenance a Sisyphean task. Thankfully, our decision to maintain meticulous JSDoc API documentation continues to pay dividends and is what makes automatically generating TypeScript definitions possible. Using the excellent https://github.com/englercj/tsd-jsdoc project we can now automatically generate and even partially validate official definitions as part of the build process. (Thanks to @bampakoa who contributed some early PRs to both CesiumJS and tsd-jsdoc over a year ago and is how I learned about tsd-jsdoc) While tsd-jsdoc output is mostly where we need it to be, we do post-processing on it as well. This lets us clean up the output and also make sure these definitions work whether users include cesium via module, i.e. `import { Cartesian3 } from 'cesium'`, or individual files, i.e. `'import Cartesian3 from 'cesium/Source/Core/Cartesian3'`. There were also some quirks of tsd-jsdoc output we fixed that may eventually turn into a PR into that project from us. The post-processing is part typescript compiler API, part string manipulation. It works and is straightforward but we might want to go full TS api in the future if we decide we need to do more complicated tasks. The output of tsd-jsdoc is currently a little noisy because of some incorrect error reporting, but I'm talking with the maintainer in englercj/tsd-jsdoc#133 to get them fixed. No need to hold up this PR for it though. The definition is generated as a single `Cesium.d.ts` file in Source, so it lives alongside Cesium.js. It is ignored by git but generated by a separate `build-ts` task as part of CI and makeZipFile. This task also validates the file by compiling it with TypeScript, so if a developer does anything too egregious, the build will fail. Definitions are automatically included in our npm packages and release zips and will be automatically used by IDEs thanks to the `types` setting in package.json. This means that IDEs such as VS Code will prefer these types over the existing `@types/cesium` version by default. I didn't want to slow the `build` step down, so I made this a separate step, but in the future we could consider running it by default and we could also unignore this file in Git so that PR reviewers can see the impact, if any, our code changes have on the generated definitions. This might be a good idea as an additional sanity check and should only actually change when the public API itself changes. But the issue would be remembering to run it before submitting the code (or we could use git hooks I suppose?) I just don't want to slow down devs so I'm hesitant to do anything like this out of the gate. We can definitely revisit in the future. A particular exciting thing about this approach is that it exposed a ton of badness in our current JSDoc markup, which is now fixed. Previously, our only concern was "does the doc look right" and we didn't pay attention to whether the meta information generated by JSDoc correctly captured type information (because up until it didn't matter). We leaned particular hard on `@exports` which acted as a catch-all but has now been completely removed from the codebase. All this means is that our documentation as a whole has now improved greatly and will continue to be maintained at this new higher level thanks to incorporating TS definition creation into our pipeline! One minor caveat here is that obviously we changed our JSDoc usage to both make it correct and also accommodate TypeScript. The main drawback to these fixes is that enums are now generated as globals in the doc, rather than modules. This means they no longer have their own dedicated page and are instead on the globals page, but I changed the code to ensure they are still in the table of contents that we generate. I think this trade-off is perfectly fine, but I wanted to mention it since it does change the doc some. We can certainly look into whether we can generate enums on their own page if we think that makes sense. (I actually like this approach a little better personally). Last major piece, the actual code. 99% of the changes in this PR only affect the JSDoc. There are two exceptions: A few of our enums also have private functions tacked onto them. I had to move these functions to be outside the initializer but otherwise they are unchanged. This ensures that a valid TS enum is generated from our code, since you can't have functions globbed onto enums in the TS world. If we were writing TS code by hand, we could use declaration merging with a namespace, but the toolchain we are using doesn't have a way to express that right now. There were two cases where these extra functions weren't private, `ComponentDataType` and `IndexDataType`. That means that as far as the TS definitions goes, the helper methods don't exist. I consder this an edge case and we can write up issues to investigate later. I'm actually not even sure if these functions are public on purposes, @lilleyse can you confirm? We had a few places where we had method signatures with optional parameters that came _before_ required parameters, which is silly. This is invalid TypeScript (and not good API design no matter the language). In 99% of cases this was `equalsEpsilon` style functions where the lhs/rhs were optional but the epsilon was not. I remember the discussion around this when we first did it because we were paranoid about defaulting to 0, but it's an edge case and it's silly so I just changed the epsilon functions to default to zero now, problem solved. Here's a high level summary of the JS changes: * Use proper `@enum` notation instead of `@exports` for enums. * Use proper `@namespace` instead of `@exports` for static classes. * Use proper `@function` instead of `@exports` for standalone functions. * Fix `Promise` markup to actually include the type in all cases, i.e. `Promise` => `Promise<void>` or `Promise<Cartesian3[]>`. * Fix bad markup that referenced types that do not exist (or no longer exist) at the spec level, `Image` => `HTMLImageElement`, `Canvas` => `HTMLCanvasElement`, etc.. `TypedArray` in particular does not exist and much be expressed as a lsit of all applicable types, `Int8Array|Uint8Array|Int16Array|Uint16Array...`. * Use dot notation instead of tilde in callbacks, to better support TypeScript, i.e. `EasingFunction~Callback` becomes `EasingFunction.Callback`. The only exception is when we had a callback type that was i.e. `exportKml~ModelCallback` becomes `exportKmlModelCallback` (a module global type rather than a type on exportKml). This is because it's not possible to have exportKml be both a function and a namespace in this current toolchain. Not a big deal either way since these are meta-types used for defining callbacks but I wanted to mention it. * There were some edge cases where private types that were referenced in the public API but don't exist in the JSDoc. These were trivial to fix by either tweaking the JSDoc to avoid leaking the type or in some cases, just as `PixelDataType`, simply exposing the private type as public. I also found a few cases where things were accidentally public, I marked these as private (these were extreme edge cases so I'm not concerned about breaking changes). Appearances took an optional `RenderState` in their options, I just changed the type to `Object` which we can clean up further later if we need to. * Lots of other little misc JSDoc issues that became obvious once we started to generate definitions (duplicate parameters for example). Thanks again to the community for helping generate ideas and discussions around TS definitions over the last few years and a big thanks to @javagl for helping behind the scenes on this specific effort by evaluating a few different approaches and workaround before we settled on this one (I'm working on a blog with all of the gory details for those interested). Finally, while I'm thrilled with how this turned out (all ~41000 lines and 1.9MB of it), I can guarantee we will uncover some issues with the type definitions as more people use it. The good news is that improving it is now just a matter of fixing the JSDoc, which will benefit the community as a whole and not just TS users. Fixes #2730 Fixes #5717
Thanks for the pull request @mramato!
Reviewers, don't forget to make sure that:
|
Goes to show, no matter how much time you spend writing up an epic and detailed PR, you still always forget to update CHANGES.md. Thanks @cesium-concierge 😄 |
If anyone would like to test this in their own TS project, you can point cesium to http://cesium-dev.s3-website-us-east-1.amazonaws.com/cesium/typescript-definitions/cesium-1.69.0-typescript-definitions34565.tgz in package.json. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I scanned through all the changes and built the TS defs and docs. Looks solid to me.
The only minor problem I ran into is links to enums in the generated documentation go to the top of global.html when you navigate from a search, instead of going directly to that type's part of the document. Looks like this is caused because ?classFilter=pixel
being appended after the hash, breaking the link.
I'm going to try building TerriaJS against this, since it's a typescript app that uses a fair bit of Cesium. I'll also wait until tomorrow to merge this to give others a chance to take a look at this PR.
It may be different in some environments. Instead, just use the normal module name, which will be resolved according to node's module resolution rules.
I changed ts-conf.json to avoid hardcoding |
Now I've also changed the "test" part of |
Well, I tried to use this in TerriaJS, and it was kind of a disaster. Some of the problems were in TerriaJS and I fixed them there. Some were in Cesium and I fixed them above. But the big remaining problem that I don't know how to fix is this: To be fair, @types/cesium didn't work in this scenario either. TerriaJS had a generated .d.ts file to make types available for individual modules. So it doesn't need to hold up this PR, but it'd still be really nice to be able to use Cesium in this way without a bunch of nonsense, if we can figure out how to make it work. We could fix it by putting a generated .d.ts file next to every Cesium source file, but hopefully there's a better way. |
Strangely, I think it's just a VSCode problem. The TerriaJS webpack build seems to be able to find the types. 🤷 |
@kring have you tried using the |
I'm building my (sadly private) project against the AWS tarball now. It's been Typescript from the beginning. Maybe 2 years ago, I started with some semi-automated typings from @Zuzon and "Harry Nicholls" (no GH listed), and I've been manually updating them based on what's in the changelog at each release. (It only takes a couple minutes every other month or so!) I put them up in a gist a while back but I've been neglecting to keep them up to date. Of course, I'm sure it's diverged from the actual implementation because I focus on the parts of the API that I personally use. After the new build finished, I got more errors than fit in my scrollback buffer. I'm assuming that at least in some cases my typings were wrong, but I may have some feedback to add here as well. Stay tuned! |
OK, first Big Thing. Basically, you have to choose between two bad options. The first is In my typings, in a few commonly used cases, I changed |
Cesium used to expose a top level function called
but I don't know if that's possible from JSDoc. Otherwise, it could at least return a Promise for My typings export public interfaces for all options-arguments, e.g. the object you pass to the Entity constructor. I find this very helpful because I often have to set a bunch of parameters conditionally so I just pass around a typed structure. Basically, anything that takes an object with more than 2-3 properties should have an exported, named interface. I went with
Most of the properties of
OK, that's my first pass. As I said it's a huge error dump so I may well have missed another couple of (types of) problems. Some of these I might be able to just fix for you, and others are going to require discussion. When I have some more cycles later on I'll take a second look. |
Sorry to keep spamming the thread but I had an idea: if you want to wire up a post-build step that runs some simple TS tests, I could contribute a bunch of test cases that capture the problems I described above. You wouldn't even need a proper test harness, just to run |
@bampakoa I couldn't get
To my tsconfig.json did the trick, forcing TypeScript to pull in Cesium's types even though it didn't know it needed to. Thanks for the suggestion! This isn't quite ideal in that it requires an extra step from Cesium users, but it's an excellent workaround. |
Thanks for all the info @thw0rted!
Yeah I think we've come to the conclusion that we need to force users to do this, due to the typescript limitation you described. This is exactly what Cesium does under-the-hood anyway, so it's no less efficient at runtime, just less efficient to type. |
Thanks for the tweaks, @kring. Thanks @thw0rted! Not spam at all, happy to have you dive and and leave valuable feedback. I'll make sure I mention the
This may be something we can fix on our end as part of our jsDoc template. I'll look into it.
Totally agree that this is unfortunate, especially since the entire
So
Long term I can definitely see moving to this approach in CesiumJS (I've actually always preferred it compared to what we do now). But it's probably outside the scope of this PR (which is just documenting what's there). It's important that we don't create fiction on the TS side of things, I want to TS definitions to mirror the code as much as possible. Knowing what I know now about JSDoc and the TS definition process, this could actually be pretty easy to add once we settle on an approach. It can even happen inline as a
They already are, or am I missing something? I think I addressed all of the non-clear-cut feedback. I'll create a task list in the PR description with all of the to-dos that have been pointed out and hopefully have this in shape by end of today. |
I'm not against this idea, and we've thought about doing similar things for Node.js. However, I think it's worth questioning how likely regressions are here once something is fixed. Having a test file with random stuff isn't super useful if we're 99.9% sure nothing will ever break. I'm trying to think of a way you would introduce "regressions" into the TS definitions that aren't also just JSDoc errors. @kring thoughts? |
Since master documented a `Proxy` base class, create it rather than using `DefaultProxy` everywhere.
Allows them to be assignable to `DataSource` in the TS definitions.
So many of the "Not assignable from" issues are because we follow a pattern like this: ImageryProvider.prototype.requestImage = DeveloperError.throwInstantiationError; And TS picks up on this and says "hey, IonImageryProvider.prototype.requestImage = function (x, y, level, request) Which leads to
This is despite the fact that the TypeScript definition file includes the correct prototype for both requestImage(x: number, y: number, level: number, request?: Request): Promise<HTMLImageElement | HTMLCanvasElement> | undefined; I think TS is being too smart and ignoring the type definition file and looking at the actual JS code in some cases. I'm not sure if this is a side-affect of Either way, I think the correct fix is to actually have Similarly, the |
Working back up the page: I'm assuming that using actual inheritance to fix the "not assignable" errors is outside the scope of this PR, but you already cut over to ES6 for everything, and classes are right there..... 😁 You're probably right about adding a TS testing step, though some find it handy to have a step in your build process that consumes generated typings just to make sure you notice when the typings go horribly wrong for whatever reason. This is a good example of a step that might only make sense to run in CI? Re: optional properties on Entity, they're optional in the constructor object but they're not optional on the class itself. Re: named interfaces for options arguments, I don't look at it as "creating a fiction". I used to default to not exporting named interfaces when I made them for my own convenience, but over time I came to realize that if I used them internally, somebody calling my code could probably use them too. One of the great strengths of TS is IDE integration, and I use Re: generic Properties, I haven't set up generics with JSDoc but it looks like tsd-jsdoc supports the @template flag from Closure. So then, maybe This is actually something I see with Events as well. I made Events generic in my typings, which is handy because then the type of the arguments in a callback get inferred correctly: class Globe {
...
readonly tileLoadProgressEvent: Event<(length: number) => void>;
...
}
globe.tileLoadProgressEvent.addEventListener(queueSize => {
if(queueSize < 10) { ... } // Typed correctly as `number`
}); This isn't just nice-to-have, it's actually necessary if you build your TS with the If I have some time later on, I might pull this branch and try to do my own Cesium build. If I get it working, I could put together an example of how generics might work using the |
Definitely outside the scope of the PR, and historically actual inheritance has performance issues (and so does ES6 vs ES5). So things like this have to take a measured approach (literally, we need to measure performance impact). I would love to use classes and inheritance throughout Cesium, and eventually we will.
This PR has that, we run the declaration file through the TS compiler with --noEmit to confirm it's valid TypeScript and that the API is internally consistent. The stuff we can't check (as you already found) is how it interacts in "real world' cases.
Interesting, thanks. We'll have to dig more into this. @kring any ideas offhand?
We would certainly be interested to hear what you find. This PR is just step 1 and we will continue to improve things as we go. But we want to get it into an official Cesium release ASAP but will absolutely make significant strides over the next few releases. |
Another issue I just uncovered that has me scratching my head.
Turns out VS Code was lying to me. |
Realized that Math/CesiumMath docs is inconsistent with master (I really had the face that Math exists as a type in Cesium). Added a task item to fix it before we merge. |
Several improvements to typings
Okay, I fixed the CesiumMath/Math issue. I also fixed the enum anchor tag issue with browsing the docs. I uncovered doc issue with |
I didn't want to lose track of this so I'm putting it here. I opened englercj/tsd-jsdoc#134 but a bit more digging led me to notice that the config file for As you can see in the linked issue, the good news is that there's actually no processing done to |
Thanks for the additional info @thw0rted I'll definitely update out config so stuff "just works" in the future. The main problem I'm trying to fix right now is that the ConstructorOptions and other types we create don't have ideal documentation. The .d.ts file ends up looking like: /**
* Initialization options for the BillboardGraphics constructor
* @property [show = true] - A boolean Property specifying the visibility of the billboard.
*/
type ConstructorOptions = {
show?: Property | boolean;
}; So /**
* Initialization options for the BillboardGraphics constructor
*/
type ConstructorOptions = {
/**
* A boolean property specifying the visibility of the billboard.
* @defaultValue true
*/
show?: Property | boolean;
}; I'm not sure if this is something on our end or something on the tsd-jsdoc side. The good news is that this is purely a doc issue and that the code itself is correct, so this may have to wait until 1.71 if there's no obvious problem (I'll write up an issue after trying to play with it some more) |
In my typings, I use |
Thanks @thw0rted. Me and @kring discussed making these an interface instead and had ultimately decided on a type. Making them an interface in light of this is still possible, but would require quite a change to all of the new ConstrutorOptions so it would be very labor intensive. I actually have a modified tsd-jsdoc spitting out the right code for typedef, which produces the "ideal" version that I pasted above, so I'm tempted to fork tsd-jsdoc and open a PR (and we could either use the forked version until the PR is merged, or just ship with what we have and then used the fixed version for 1.71 once the PR is accepted. @kring your thoughts here? |
Actually, I think interface may be the right answer because I don't think it's possible to have a I think either way, the answer is to merge this PR (assuming no other changes require) and sort it out in the next release. The type/interface difference should be negligible from a compatibility standpoint with the next release. |
Also opt-in tsd-jsdoc so we can use @template in the future.
@thw0rted I ended up opening that tsd-jsdoc PR to improve property output I mentioned: englercj/tsd-jsdoc#135 |
FYI, I tweaked CHANGES.md in master. For anyone who stumbled onto this PR from elsewhere, there's a blog post with a full overview of how we selected this approach and some details about how it works: https://cesium.com/blog/2020/06/01/cesiumjs-tsd/ (Link won't be live until 6/1) |
* @param {Number} [tileHeight=256] The height of the tile for level-of-detail selection purposes. | ||
* @property {Color} [color=Color.YELLOW] The color to draw the tile box and label. | ||
* @property {Number} [tileWidth=256] The width of the tile for level-of-detail selection purposes. | ||
* @property {Number} [tileHeight=256] The height of the tile for level-of-detail selection purposes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dang it, I knew I was going to miss one of these :-/
Hey @mramato , I think during your review you mentioned something about |
I believe there is also a |
It's been a long requested feature for CesiumJS to have official TypeScript type definitions.
While the community has done a yeoman's job of manually supporting various efforts, the most recent incarnation of which is
@types/cesium
, the sheer scale and ever-evolving nature of Cesium's code base makes manual maintenance a Sisyphean task.Thankfully, our decision to maintain meticulous JSDoc API documentation continues to pay dividends and is what makes automatically generating TypeScript definitions possible. Using the excellent https://github.com/englercj/tsd-jsdoc project (and a bunch of cleanup on our end) we can now automatically generate and even partially validate official definitions as part of the build process. (Thanks to @bampakoa who contributed some early PRs to both CesiumJS and tsd-jsdoc over a year ago and is how I learned about tsd-jsdoc)
While tsd-jsdoc output is mostly where we need it to be, we do post-processing on it as well. This lets us clean up the output and also make sure these definitions work whether users include cesium via module, i.e.
import { Cartesian3 } from 'cesium'
, or individual files, i.e.'import Cartesian3 from 'cesium/Source/Core/Cartesian3'
. There were also some quirks of tsd-jsdoc output we fixed that may eventually turn into a PR into that project from us. The post-processing is part typescript compiler API, part string manipulation. It works and is straightforward but we might want to go full TS api in the future if we decide we need to do more complicated tasks. The output of tsd-jsdoc is currently a little noisy because of some incorrect error reporting, but I'm talking with the maintainer in englercj/tsd-jsdoc#133 to get them fixed. No need to hold up this PR for it though.The definition is generated as a single
Cesium.d.ts
file in Source, so it lives alongside Cesium.js. It is ignored by git but generated by a separatebuild-ts
task as part of CI and makeZipFile. This task also validates the file by compiling it with TypeScript, so if a developer does anything too egregious, the build will fail. Definitions are automatically included in our npm packages and release zips and will be automatically used by IDEs thanks to thetypes
setting in package.json. This means that IDEs such as VS Code will prefer these types over the existing@types/cesium
version by default.I didn't want to slow the
build
step down, so I made this a separate step, but in the future we could consider running it by default and we could also unignore this file in Git so that PR reviewers can see the impact, if any, our code changes have on the generated definitions. This might be a good idea as an additional sanity check and should only actually change when the public API itself changes. But the issue would be remembering to run it before submitting the code (or we could use git hooks I suppose?) I just don't want to slow down devs so I'm hesitant to do anything like this out of the gate. We can definitely revisit in the future.A particular exciting thing about this approach is that it exposed a ton of badness in our current JSDoc markup, which is now fixed. Previously, our only concern was "does the doc look right" and we didn't pay attention to whether the meta information generated by JSDoc correctly captured type
information (because up until it didn't matter). We leaned particular hard on
@exports
which acted as a catch-all but has now been completely removed from the codebase. All this means is that our documentation as a whole has now improved greatly and will continue to be maintained at thisnew higher level thanks to incorporating TS definition creation into our pipeline!
One minor caveat here is that obviously we changed our JSDoc usage to both make it correct and also accommodate TypeScript. The main drawback to these fixes is that enums are now generated as globals in the doc, rather than modules. This means they no longer have their own dedicated page and are instead on the globals page, but I changed the code to ensure they are still in the table of contents that we generate. I think this trade-off is perfectly fine, but I wanted to mention it since it does change the doc some. We can certainly look into whether we can generate enums on their own page if we think that makes sense. (I actually like this approach a little better personally).
Last major piece, the actual code. 99% of the changes in this PR only affect the JSDoc. There are two exceptions:
A few of our enums also have private functions tacked onto them. I had to move these functions to be outside the initializer but otherwise they are unchanged. This ensures that a valid TS enum is generated from our code, since you can't have functions globbed onto enums in the TS world. If we were writing TS code by hand, we could use declaration merging with a namespace, but the toolchain we are using doesn't have a way to express that right now. There were two cases where these extra functions weren't private,
ComponentDataType
andIndexDataType
. That means that as far as the TS definitions goes, the helper methods don't exist. I consder this an edge case and we can write up issues to investigate later. I'm actually not even sure if these functions are public on purposes, @lilleyse can you confirm?We had a few places where we had method signatures with optional parameters that came before required parameters, which is silly. This is invalid TypeScript (and not good API design no matter the language). In 99% of cases this was
equalsEpsilon
style functions where the lhs/rhs were optional but the epsilon was not. I remember the discussion around this when we first did it because we were paranoid about defaulting to 0, but it's an edge case and it's silly so I just changed the epsilon functions to default to zero now, problem solved.Here's a high level summary of the JS changes:
Use proper
@enum
notation instead of@exports
for enums.Use proper
@namespace
instead of@exports
for static classes.Use proper
@function
instead of@exports
for standalone functions.Fix
Promise
markup to actually include the type in all cases, i.e.Promise
=>Promise<void>
orPromise<Cartesian3[]>
.Fix bad markup that referenced types that do not exist (or no longer exist) at the spec level,
Image
=>HTMLImageElement
,Canvas
=>HTMLCanvasElement
, etc..TypedArray
in particular does not exist and much be expressed as a lsit of all applicable types,Int8Array|Uint8Array|Int16Array|Uint16Array...
.Use dot notation instead of tilde in callbacks, to better support TypeScript, i.e.
EasingFunction~Callback
becomesEasingFunction.Callback
. The only exception is when we had a callback type that was i.e.exportKml~ModelCallback
becomesexportKmlModelCallback
(a module global type rather than a type on exportKml). This is because it's not possible to have exportKml be both a function and a namespace in this current toolchain. Not a big deal eitherway since these are meta-types used for defining callbacks but I wanted to mention it.
There were some edge cases where private types that were referenced in the public API but don't exist in the JSDoc. These were trivial to fix by either tweaking the JSDoc to avoid leaking the type or in some cases, just as
PixelDataType
, simply exposing the private type as public. I also found a few cases where things were accidentally public, I marked these as private (these were extreme edge cases so I'm not concerned about breaking changes). Appearances took an optionalRenderState
in their options, I just changed the type toObject
which we can clean up further later if we need to.Lots of other little misc JSDoc issues that became obvious once we started to generate definitions (duplicate parameters for example).
Thanks again to the community for helping generate ideas and discussions around TS definitions over the last few years and a big thanks to @javagl for helping behind the scenes on this specific effort by evaluating a few different approaches and workaround before we settled on this one (I'm
working on a blog with all of the gory details for those interested).
Finally, while I'm thrilled with how this turned out (all ~41000 lines and 1.9MB of it), I can guarantee we will uncover some issues with the type definitions as more people use it. The good news is that improving it is now just a matter of fixing the JSDoc, which will benefit the community as a whole and not just TS users.
Fixes #2730
Fixes #5717
ToDo based on feedback below:
Proxy
interface instead of usingDefaultProxy
everywhere@typedef
types don't have conformant ts-doc.