@@ -16,12 +16,12 @@ import { VirtualTypeScriptContext } from "../context";
1616import type { TSESParseForESLintResult } from "../types" ;
1717import type ESTree from "estree" ;
1818import type { SvelteAttribute , SvelteHTMLElement } from "../../../ast" ;
19+ import { globalsForSvelte5 , globals } from "../../../parser/globals" ;
1920
2021export type AnalyzeTypeScriptContext = {
2122slots :Set < SvelteHTMLElement > ;
2223} ;
2324
24- const RESERVED_NAMES = new Set < string > ( [ "$$props" , "$$restProps" , "$$slots" ] ) ;
2525/**
2626 * Analyze TypeScript source code.
2727 * Generate virtual code to provide correct type information for Svelte store reference namess and scopes.
@@ -75,8 +75,8 @@ function analyzeStoreReferenceNames(
7575if (
7676// Begin with `$`.
7777reference . identifier . name . startsWith ( "$" ) &&
78- // Ignoreit is a reserved variable.
79- ! RESERVED_NAMES . has ( reference . identifier . name ) &&
78+ // Ignoreglobals
79+ ! globals . includes ( reference . identifier . name ) &&
8080// Ignore if it is already defined.
8181! programScope . set . has ( reference . identifier . name )
8282) {
@@ -215,6 +215,59 @@ function analyzeDollarDollarVariables(
215215) ;
216216}
217217
218+ addSvelte5Globals ( ) ;
219+
220+ function addSvelte5Globals ( ) {
221+ for ( const svelte5Global of globalsForSvelte5 ) {
222+ if (
223+ ! scopeManager . globalScope ! . through . some (
224+ ( reference ) => reference . identifier . name === svelte5Global ,
225+ )
226+ ) {
227+ continue ;
228+ }
229+ switch ( svelte5Global ) {
230+ case "$state" :{
231+ appendDeclareFunctionVirtualScript (
232+ svelte5Global ,
233+ "<T>(initial: T): T" ,
234+ ) ;
235+ appendDeclareFunctionVirtualScript (
236+ svelte5Global ,
237+ "<T>(): T | undefined" ,
238+ ) ;
239+ break ;
240+ }
241+ case "$derived" :{
242+ appendDeclareFunctionVirtualScript (
243+ svelte5Global ,
244+ "<T>(expression: T): T" ,
245+ ) ;
246+ break ;
247+ }
248+ case "$effect" :{
249+ appendDeclareFunctionVirtualScript (
250+ svelte5Global ,
251+ "(fn: () => void | (() => void)): void" ,
252+ ) ;
253+ appendDeclareNamespaceVirtualScript (
254+ svelte5Global ,
255+ "export function pre(fn: () => void | (() => void)): void;" ,
256+ ) ;
257+ break ;
258+ }
259+ case "$props" :{
260+ appendDeclareFunctionVirtualScript ( svelte5Global , "<T>(): T" ) ;
261+ break ;
262+ }
263+ default :{
264+ const _ :never = svelte5Global ;
265+ throw Error ( `Unknown global:${ _ } ` ) ;
266+ }
267+ }
268+ }
269+ }
270+
218271/** Append declare virtual script */
219272function appendDeclareVirtualScript ( name :string , type :string ) {
220273ctx . appendVirtualScript ( `declare let${ name } :${ type } ;` ) ;
@@ -242,6 +295,59 @@ function analyzeDollarDollarVariables(
242295return true ;
243296} ) ;
244297}
298+
299+ /** Append declare virtual script */
300+ function appendDeclareFunctionVirtualScript ( name :string , type :string ) {
301+ ctx . appendVirtualScript ( `declare function${ name } ${ type } ;` ) ;
302+ ctx . restoreContext . addRestoreStatementProcess ( ( node , result ) => {
303+ if (
304+ node . type !== "TSDeclareFunction" ||
305+ ! node . declare ||
306+ node . id ?. type !== "Identifier" ||
307+ node . id . name !== name
308+ ) {
309+ return false ;
310+ }
311+ const program = result . ast ;
312+ program . body . splice ( program . body . indexOf ( node ) , 1 ) ;
313+
314+ const scopeManager = result . scopeManager as ScopeManager ;
315+
316+ // Remove `declare` variable
317+ removeAllScopeAndVariableAndReference ( node , {
318+ visitorKeys :result . visitorKeys ,
319+ scopeManager,
320+ } ) ;
321+
322+ return true ;
323+ } ) ;
324+ }
325+
326+ function appendDeclareNamespaceVirtualScript ( name :string , script :string ) {
327+ ctx . appendVirtualScript ( `declare namespace $effect {${ script } }` ) ;
328+ ctx . restoreContext . addRestoreStatementProcess ( ( node , result ) => {
329+ if (
330+ node . type !== "TSModuleDeclaration" ||
331+ ! node . declare ||
332+ node . id ?. type !== "Identifier" ||
333+ node . id . name !== name
334+ ) {
335+ return false ;
336+ }
337+ const program = result . ast ;
338+ program . body . splice ( program . body . indexOf ( node ) , 1 ) ;
339+
340+ const scopeManager = result . scopeManager as ScopeManager ;
341+
342+ // Remove `declare` variable
343+ removeAllScopeAndVariableAndReference ( node , {
344+ visitorKeys :result . visitorKeys ,
345+ scopeManager,
346+ } ) ;
347+
348+ return true ;
349+ } ) ;
350+ }
245351}
246352
247353/**