-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
chore:Update for TS7 #16485
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?
chore:Update for TS7 #16485
Conversation
I am testing Typescript 7's JS support, which I've largely rewritten during the switch to Go. That means Javascript code will need to change much more than Typescript code. Fortunately, most of the changes are for the better: Javascript semantics are now nearly identical to Typescript semantics. It's much stricter and no longer has some persistent bugs that arose from shady JS handling I wrote years ago. This PR changes Svelte so that it compiles both with TS5.* and TS7, which means that occasionally there are duplicative or non-obvious changes. I'll annotate the interesting changes to explain why I made them. Because TS7 is quite a way off, I don't know whether you'll want to take this PR. Most of the changes are for the better, because they're due to stricter TS-aligned checking. But some are neutral and there is the previously mentioned duplication in a few places.
🦋 Changeset detectedLatest commit: c2f5e05 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
@@ -26,7 +26,7 @@ await createBundle({ | |||
// so that types/properties with `@internal` (and its dependencies) are removed from the output | |||
stripInternal: true, | |||
paths: Object.fromEntries( | |||
Object.entries(pkg.imports).map(([key, value]) => { | |||
Object.entries(pkg.imports).map(/** @param {[string,any]} import */([key, value]) => { |
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.
pkg.imports: any
and Object.entries
now infers [string, unknown]
instead of [string, any]
. This is stricter, and what happens in .ts files, but requires an explicit param type.
This shows up quite a bit in this PR.
@@ -9,8 +9,8 @@ import { | |||
import { regex_ends_with_whitespace, regex_starts_with_whitespace } from '../../patterns.js'; | |||
import { get_attribute_chunks, is_text_attribute } from '../../../utils/ast.js'; | |||
|
|||
/** @typedef {NODE_PROBABLY_EXISTS | NODE_DEFINITELY_EXISTS} NodeExistsValue */ | |||
/** @typedef {FORWARD | BACKWARD} Direction */ | |||
/** @typedef {typeof NODE_PROBABLY_EXISTS | typeof NODE_DEFINITELY_EXISTS} NodeExistsValue */ |
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.
JS type annotations no longer insert typeof
in places where it finds a value but expects a type. You have to do it explicitly, like in TS.
@@ -14,6 +14,7 @@ export default function check_graph_for_cycles(edges) { | |||
}, new Map()); | |||
|
|||
const visited = new Set(); | |||
/** @type {Set<T>} */ |
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.
new Set(): Set<unknown>
now, not Set<any>
, so you have to explicitly provide a type. I think I gave real types throughout this PR rather than Set<any>
, so the typing ends up better than before.
@@ -55,7 +55,7 @@ export function convert(source, ast) { | |||
|
|||
// Insert svelte:options back into the root nodes | |||
if (/** @type {any} */ (options)?.__raw__) { | |||
let idx = node.fragment.nodes.findIndex((node) => options.end <= node.start); | |||
let idx = node.fragment.nodes.findIndex((node) => /** @type {any} */ (options).end <= node.start); |
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.
same as before; options
would be unknown
in TS7 without this cast.
@@ -64,7 +64,7 @@ export function hmr(original, get_source) { | |||
// @ts-expect-error | |||
wrapper[FILENAME] = original[FILENAME]; | |||
|
|||
// @ts-expect-error | |||
// @ts-ignore |
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 error being ignored here is bogus, a result of wonky JS checking that mistakenly causes a circularity. In TS7, this bug is fixed. If this were a complete upgrade to TS7, I would remove this line, but since I want it to compile on TS5 and TS7, I switched it to ts-ignore.
@@ -160,10 +160,14 @@ export function createEventDispatcher() { | |||
e.lifecycle_outside_component('createEventDispatcher'); | |||
} | |||
|
|||
/** |
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.
same: signature-to-signature checking (like when you're checking that a returned function has the right type) is stricter in TS7, so you have to explicitly note that detail
and options
are optional.
I also improved the cast on type but I can't remember if that's actually necessary.
@@ -87,15 +88,15 @@ function normalize_html(window, html) { | |||
/** @param {any} node */ | |||
function normalize_children(node) { | |||
// sort attributes | |||
const attributes = Array.from(node.attributes).sort((a, b) => { | |||
const attributes = Array.from(node.attributes).sort((/** @type {any} */ a,/** @type {any} */ b) => { |
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.
same as above; Array.from(node.attributes)
infers unknown[]
in TS7.
@@ -54,14 +56,24 @@ class Animation { | |||
|
|||
/** | |||
* @param {HTMLElement} target | |||
* @param {Keyframe[]} keyframes | |||
* @param {{ duration: number, delay: number }} options | |||
* @param {Keyframe[] | PropertyIndexedKeyframes | null} keyframes |
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 kind of went overboard here fixing up this test to handle the DOM types. It's probably better to turn a bunch of these types to any
instead. I needed to do something because of the improved signature arity checking in TS7.
@@ -189,13 +201,15 @@ function interpolate(a, b, p) { | |||
* @param {{duration: number, delay: number}} options | |||
* @returns {globalThis.Animation} | |||
*/ | |||
// @ts-ignore |
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 location of the error to be ignored moved in TS7 to match the location reported in a .ts file
@@ -43,6 +43,7 @@ export function create_deferred() { | |||
/** @param {any} [reason] */ | |||
let reject = (reason) => {}; | |||
|
|||
/** @type {Promise<any>} */ |
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.
TS7 inferred promise: Promise<unknown>
without an explicit annotation.
if (arguments.length > 0) { | ||
const new_value = mutation ? get(d) : runes && bindable ? proxy(value) : value; | ||
return /** @type {() => V} */ ( | ||
function (/** @type {any} */ value, /** @type {boolean} */ mutation) { |
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.
after running prettier, Hide Whitespace is basically required to review this PR
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'm really excited to see TSGo hit the ground -- it's a gargantuan undertaking from you guys. We're glad we can be a bit of a guinea pig for typed JS! Feel free to run sveltejs/kit
through its paces as well -- that one has some demons, especially in all of the crazy rootDirs
and generated types stuff we do.
@@ -1,9 +1,9 @@ | |||
/** @import { Equals } from '#client' */ | |||
|
|||
/** @type {Equals} */ | |||
export function equals(value) { | |||
export const equals = function (value) { |
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.
sigh, this is actually one of the few places I liked JSDoc more than TS -- the fact that there's no way to type function
declarations in TS grinds my gears!
FWIW this actually is going to negatively impact us -- in our language tools, whenever you export function load
from a +page
file, we insert /** @type {Load} */
above it to provide you generated types without you having to explicitly import and use them. I'm sure we can find a workaround but it'll at least be somewhat more difficult now, as we can't just change function
declarations to const {name} = () => {}
as it's semantically different
Just to note it, we don't yet do rootDirs because we thought we were going to remove that feature (it's wonky and usually has much better replacements, which IMO you all should consider, for the same reasons |
I am testing Typescript 7's JS support, which I've largely rewritten during the switch to Go. That means Javascript code will need to change much more than Typescript code. Fortunately, most of the changes are for the better: Javascript semantics are now nearly identical to Typescript semantics. It's much stricter and no longer has some persistent bugs that arose from shady JS handling I wrote years ago.
This PR changes Svelte so that it compiles both with TS5.* and TS7, which means that occasionally there are duplicative or non-obvious changes. I'll annotate the interesting changes to explain why I made them.
Because TS7 is quite a way off, I don't know whether you'll want to take this PR. Most of the changes are for the better, because they're due to stricter TS-aligned checking. But some are neutral and there is the previously mentioned duplication in a few places.
Temporary note: if you try this with the nightly ts-native vscode extension, it will still be missing one or two bug fixes until today (2025-07-23) or tomorrow (2025-07-24).