-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Types: Enable incremental JSDoc type checking #13104
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
base: main
Are you sure you want to change the base?
Conversation
|
Thank you for the pull request, @donmccurdy! ✅ We can confirm we have a CLA on file for you. |
jjspace
left a comment
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.
Thanks for this @donmccurdy! Overall I'm hugely in favor of this change. It should let us get more out of our intellisense and start catching some type errors even before switching fully to TS.
Can you please add a section to our documentation pages about this? Probably part of the Contribution guides, maybe the CodingGuide? I also had a few more comments to help guide what gets documented.
f2cef71 to
fbe8a40
Compare
84dfb32 to
c8a10b5
Compare
|
@jjspace I think all feedback on the PR has been addressed! Draft documentation in the coding guide: I've moved the I also attempted a bulk conversion to ES6 classes for That's too large to review and merge in bulk, for sure, but still it's encouraging to see tests passing after excluding a handful of files from the conversion. |
jjspace
left a comment
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.
Couple quick comments on the new docs, thanks for adding those!
|
|
||
| ## Type Checking | ||
|
|
||
| We are incrementally adopting [type checking for JavaScript files](https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html). As of January 2026, type checks are enabled on a file-by-file basis, with `// @ts-check` annotations at the top of a file used to opt in. As adoption progresses, we expect this pattern will eventually be flipped to an opt-opt annotation instead. To see type system hints and errors in some editors or IDEs, you may need to configure or install TypeScript language server support. When in doubt, VSCode supports TypeScript language services [by default](https://code.visualstudio.com/docs/nodejs/working-with-javascript). |
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.
Typo
| We are incrementally adopting [type checking for JavaScript files](https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html). As of January 2026, type checks are enabled on a file-by-file basis, with `// @ts-check` annotations at the top of a file used to opt in. As adoption progresses, we expect this pattern will eventually be flipped to an opt-opt annotation instead. To see type system hints and errors in some editors or IDEs, you may need to configure or install TypeScript language server support. When in doubt, VSCode supports TypeScript language services [by default](https://code.visualstudio.com/docs/nodejs/working-with-javascript). | |
| We are incrementally adopting [type checking for JavaScript files](https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html). As of January 2026, type checks are enabled on a file-by-file basis, with `// @ts-check` annotations at the top of a file used to opt in. As adoption progresses, we expect this pattern will eventually be flipped to an opt-out annotation instead. To see type system hints and errors in some editors or IDEs, you may need to configure or install TypeScript language server support. When in doubt, VSCode supports TypeScript language services [by default](https://code.visualstudio.com/docs/nodejs/working-with-javascript). |
| - [Type Checking JavaScript Files \| TypeScript](https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html) | ||
| - [JSDoc Reference \| TypeScript](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html) | ||
| - [JSDoc Cheatsheet and Type Safety Tricks](https://docs.joshuatz.com/cheatsheets/js/jsdoc/) by Joshua Tzucker |
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 think we need to be careful about links like these. TS has sort of expanded or co-opted JSDoc for extra functionality that is not part of JSDoc itself. Our doc generation still uses pure JSDoc so we are beholden to only features it supports. The @import tag is helpful but I feel like that might be the only exception we want to make until our doc generation is updated.
For example in the TS JSDoc Reference it mentions the @staisfies tag. This is not a JSDoc tag and adding it will result in an error ERROR: The @satisfies tag is not a known tag.. I didn't test the others but I'm guessing there are other inconsistencies like this.
Also the very first recommendation in the Cheatsheet shows how to typeguard functions using @returns {value is TYPE}. This is also not recognized by JSDoc and results in an error like:
ERROR: Unable to parse a tag's type expression for source file /home/[user]/Programming/cesium/packages/engine/Source/Core/defined.js in line 28 with tag title "return" and text "{obj is Person}": Invalid type expression "obj is Person": Expected "|" but "i" found.
I bet we could make more edits to our JSDoc config/generation to adapt for more tags but I'm not sure the level of effort there. I mostly bring it up as a word of caution. Maybe all it needs is a warning that our doc gen still needs to work and to be careful. Or a comment that we need to restrict to only official JSDoc tags? Happy to discuss
| ``` | ||
| 3. **Prefer `@ts-expect-error` over `@ts-ignore`.** Sometimes a source file's types are _mostly_ consistent, but a few stubborn errors remain unsolved. These may be blocked by out-of-scope work, or may simply be unjustifiably difficult to solve in JSDoc-based types. Use `@ts-expect-error` annotations to relax the type system for specific lines. Unlike `@ts-ignore`, `@ts-expect-error` will raise errors when the line no longer contains an error, making it easier to clean up annotations later on. | ||
| 4. **Prefer `unknown` or `@ts-expect-error` over `any`.** Casting types to `any` forces them to be accepted everywhere, and effectively disables all type-checking dependent on that type. This tends to propagate throughout a type system, reducing the effectiveness of type checks, and should be avoided when possible. Prefer casting to `unknown`, or using a `@ts-expect-error` annotation. For example, when defining an object with string keys, with values whose types we don't care about, prefer `Record<string, unknown>` to `Record<string, any>`. | ||
| 5. **Type-only imports.** When JSDoc annotations depend on types not otherwise imported in a source file, it will be necessary to tell TypeScript where to find them. To avoid otherwise-unused imports, use type-only imports in separate one-line JSDoc comments: |
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.
The very first google search for "import type in JSDoc" points to an older syntax that still works for the TS side of things
/**
* @typedef {import('./File1.js').MyObject1} MyObject1
*/However this is not valid JSDoc and will break things. I think it's worth calling out here to not use this syntax and instead always rely only on the @import tag.
| npx lebab packages/engine/Source/Core/Cartesian2.js \ | ||
| -o packages/engine/Source/Core/Cartesian2.js --transform class | ||
| ``` | ||
| 3. **Prefer `@ts-expect-error` over `@ts-ignore`.** Sometimes a source file's types are _mostly_ consistent, but a few stubborn errors remain unsolved. These may be blocked by out-of-scope work, or may simply be unjustifiably difficult to solve in JSDoc-based types. Use `@ts-expect-error` annotations to relax the type system for specific lines. Unlike `@ts-ignore`, `@ts-expect-error` will raise errors when the line no longer contains an error, making it easier to clean up annotations later on. |
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 like this suggestion for forward compatibility and cleanup. (a quick search led to articles that agree too)
Can we expand this to always include a reason with the disable comment?
It also could be good to look at enforcing this programmatically in eslint. We're already using typescript-eslint for Sandcastle but maybe it's easy to expand to engine files too? It looks like there's a ban-ts-comment rule for this to ban ts-ignore and require-reason for expect-error comments.
|
This PR is looking great to me! While it doesn't need to hold up merging what we have here, I wonder if there are any TS best practices recommended by the Cesium ion team or the iTwin.js team—Maybe @tfili @angrycat9000 or @markschlosseratbentley could point us to any relevant guides? |
Description
Summary
Enables IDEs with TypeScript language server support (such as VSCode) to infer types from JSDoc and detect type errors automatically. The PR is 'minimal' in the sense that it does not require migrating code into subpackages, and does not require replacing tsd-jsdoc. Either of those larger changes might still be preferable for other reasons, certainly. Adoption of TypeScript checks could be entirely incremental with this approach; we can turn type-checking on one file at a time.
Changes
packages/engine/tsdoc.json, with type-checking disabled for all JS files by default. Individual JS files may opt-in to type checking with a// @ts-checkcomment at top of file./** @import Cartesian3 from './Cartesian3.js'; */. TypeScript understands these, but JSDoc errors on them, so we update the JSDoc configuration to ignore@importtags. Huge thanks to @jjspace for this solution!tscand check types, for files that we have opted in.Background
Minimal subset of work from 12/16/2025 hackathon day, including work from @jjhembd, @jdehorty, @jjspace, and myself. Other tracks explored in the hackathon — including JSDoc-TS compatibility conversion with Gemini, smaller package reorganization, build system updates, documentation generation with typedoc, , etc. — are on the
core-mathbranch. We'll likely want to use some of those results too, but this PR might be the minimum-viable starting point.Issue number and link
Testing plan
Run
npm run tsc, and observe no errors reported. Addthis.x = 'hello world'to the Cartesian2 constructor, runnpm run tscagain, and see expected error output:The same error should appear in your editor/IDE, without explicitly running
tsc, if the editor supports the TypeScript Language Server.Author checklist
CONTRIBUTORS.mdCHANGES.mdwith a short summary of my changePR Dependency Tree
This tree was auto-generated by Charcoal