Skip to content

Migrate check-types from closure to tsc#35243

Closed
samouri wants to merge 4 commits intoampproject:mainfrom
samouri:checktypes-tsc
Closed

Migrate check-types from closure to tsc#35243
samouri wants to merge 4 commits intoampproject:mainfrom
samouri:checktypes-tsc

Conversation

@samouri
Copy link
Copy Markdown
Member

@samouri samouri commented Jul 15, 2021

summary

There are various inconsistencies between TS and Closure that mean this change isn't as simple as flipping a switch.
From what I can tell, TS seems to catch more and is more pedantic around denying implicit any, and Closure is smarter about knowing an item is not null after a devAssert.

Overall there are ~250 errors in src/core/**/*.js (the only type checked code), most of which seem trivially solvable.
Some examples of changes we'll need to make:

1. Convert externs to .d.ts

This is relatively straightforward. For example with error.extern.js we can change it to

// error.d.ts
interface Error {
  messageArray: undefined | Array<any>;
}

2. While loop array.pop() iteration

Closure is more intelligent about determining that an element cannot be null, specifically for the pattern called out here: microsoft/TypeScript#23405. We'll need to work around it for TS. Likely by taking advantage of type casting and NonNullable<typeof arr[0]>

3. File path types

Closure supporting typedefs references in other files. I'm not sure TS can do that unless the variables are in scope (imported) or are declared globally.

4. asserts

Closure allows our devAssert to both return a value and imply that the value is no longer null everywhere after it.
TS supports a notion Utility types which are allowed within JSDoc as well. We can convert all of our assertions to use this. Instead of returning T, our asserts should return Nonnullable<T>. Note that this doesn't completely solve it, since there is still a leftover issue.

function example() {
  /** @type {number | null} */
  let x = 5

  devAssert(x);
  x; // In closure, this type would just be number. TS still thinks it may be null.
}

5. Incorrect/weird inference

TS will sometimes prioritize a node_modules based type instead of a DOM based one. For example, usage of setTimeout sometimes ends up referring to the Node.js one instead of Window.setTimeout which has an incompatible type definition. A hacky workaround is to convert the call into window.setTimeout, but ideally we could completely exclude certain types from the compilation (i.e. node_modules/@types/node/**/*.ts)

@samouri samouri changed the title Migrate typechecking from closure to tsc Migrate check-types from closure to tsc Jul 15, 2021
@lgtm-com
Copy link
Copy Markdown

lgtm-com bot commented Jul 15, 2021

This pull request introduces 1 alert when merging f11f3a8 into 09c92d8 - view on LGTM.com

new alerts:

  • 1 for Expression has no effect

@lgtm-com
Copy link
Copy Markdown

lgtm-com bot commented Jul 15, 2021

This pull request introduces 1 alert when merging 5a1eeeb into 09c92d8 - view on LGTM.com

new alerts:

  • 1 for Expression has no effect

@samouri
Copy link
Copy Markdown
Member Author

samouri commented Jan 25, 2022

Completed in #37141 🎉

@samouri samouri closed this Jan 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant