[Bug?]: The example in the docs doesn't seam to work.
Duplicates
- [X] I have searched the existing issues
Latest version
- [X] I have tested the latest version
Current behavior 😯
The example in the documentation doesn't seam to work.
declare module "@solidjs/start/server" {
interface RequestEventLocals {
myNumber: number;
someString: string;
}
}
locals property within the RequestEvent doesn't have any types declared in global.d.ts. For example in one of the routes:
import { getRequestEvent } from 'solid-js/web'
const getMessage = cache(async () => {
'use server'
const event = getRequestEvent()
// event?.locals is not typed
return
}, 'message')
export const route = {
load: () => getMessage(),
}
and my global.d.ts has
declare module '@solidjs/start/server' {
interface RequestEventLocals {
myNumber: number
someString: string
}
}
Expected behavior 🤔
No response
Steps to reproduce 🕹
Steps:
- Create an solid-start app using one of the templates
- Declare '@solidjs/start/server' within the global.d.ts file
- Try accessing
event.locals.<SOMETHING>within a route function
Context 🔦
No response
Your environment 🌎
No response
I am going to ask for a reproduction. We have an example template experiments that has this usage in it and it appears to be working.
https://github.com/solidjs/solid-start/blob/main/examples/experiments/src/entry-server.tsx#L4-L9 https://github.com/solidjs/solid-start/blob/main/examples/experiments/src/routes/index.tsx#L12-L13
(the example uses an undeclared value, but switch it to n/s shows the right types).
@ryansolid It does work if declared within entry-server.tsx. I created a repository based on a basic template. The types still don't work when declared within global.d.ts file. Look at the line 9 in the routes/index.tsx file.
@RonenEizen for me it started to work also in the global.d.ts when changing the
/// <reference types="@solidjs/start/env" />
to
import "@solidjs/start/env";
(make sure to restart ts server to see the effect)
I am not sure why this is the case though.
Oh.. hmm so this is a weird typescript-ism.. Lovely. Not sure what to do with this then.
I think I got to the bottom of the behaviour, it is described here ambient vs augmented modules. Just adding an export {} is fixing the issue but seems weird to just have it dangling there with no meaning.
Checking the Astro repo they are using declare namespace App for typing their locals -> docs, i am not sure there is an easier way around this.
I am personally fine with the workaround. Should I keep this issue? Or would you rather have it resolved?
@ryansolid i guess it would make sense to rework to namespace? i threw together the needed changes here #1469 -> than the new way to overwrite the RequestEventLocals would look like this:
declare namespace App {
interface RequestEventLocals {
myNumber: number;
someString: string;
}
}
The old first line reference is not needed.
I think the only thing needed to get the @solidjs/start/env types working is to include ./env.d.ts in the exports property of package.json.
The schema documentation for package.json says:
The "exports" field is used to restrict external access to non-exported module files, also enables a module to import itself using "name".
Edit: For TypeScript <5 you may also need to add it to the typesVersions property of package.json.
Edit again: To clarify, I'm talking about the package.json of solid-start.
@rmacfie I did a couple of tests to figure it out and I did not test the specific suggestion. Did you test this?
From my understanding the problem has nothing to do with the actual reference vs. import. Just TypeScript switching the module interpretation from ambient (with reference) to augmented with any import / export statement, no need to import the env.d.ts file at all.
@rmacfie I did a couple of tests to figure it out and I did not test the specific suggestion. Did you test this?
Yes, I modified node_modules/@solidjs/start/package.json to include ./env.d.ts in the exports section. This makes references to @solidjs/start/env work.
If I understand correctly, once exports in package.json is declared it will act as a white-list for Typescript, so it's logical that @solidjs/start/env just doesn't work correctly until this is fixed.
@rmacfie can you share the test setup, i tried making the stated modifications but it does not work for me.
@rmacfie can you share the test setup, i tried making the stated modifications but it does not work for me.
I made a proof of concept of changes in solid-start and the basic example with some dummy extensions to the ImportMetaEnv and RequestEventLocals types. You can see the diff here:
https://github.com/solidjs/solid-start/compare/main...rmacfie:solid-start:issue-1466-poc
In examples/basic/src/routes/about.tsx you can see
console.log(import.meta.env.FOO);
console.log(requestEvent.locals.foo);
The foo properties are typed according to the extensions declared in examples/basic/src/global.d.ts.
I think I got to the bottom of the behaviour, it is described here ambient vs augmented modules. Just adding an export {} is fixing the issue but seems weird to just have it dangling there with no meaning.
It may look weird but I believe this is the recommended pattern to follow for this situation.
It has probably worked at some point without export {}, but a change in tsconfig.json broke it, possible the addition of "isolatedModules": true.
@rmacfie
@rmacfie can you share the test setup, i tried making the stated modifications but it does not work for me.
I made a proof of concept of changes in solid-start and the basic example with some dummy extensions to the
ImportMetaEnvandRequestEventLocalstypes. You can see the diff here: main...rmacfie:solid-start:issue-1466-pocIn
examples/basic/src/routes/about.tsxyou can seeconsole.log(import.meta.env.FOO); console.log(requestEvent.locals.foo);The foo properties are typed according to the extensions declared in
examples/basic/src/global.d.ts.
Yes that is working because adding an empty export {}; in examples/basic/src/global.d.ts is telling typescript to interpret as an module augmentation. No other change needed from my testing experience.
I think I got to the bottom of the behaviour, it is described here ambient vs augmented modules. Just adding an export {} is fixing the issue but seems weird to just have it dangling there with no meaning.
It may look weird but I believe this is the recommended pattern to follow for this situation.
It has probably worked at some point without
export {}, but a change intsconfig.jsonbroke it, possible the addition of"isolatedModules": true.
The typescript docs state This module declaration syntax becomes a module augmentation when the file is a module, meaning it has a top-level import or export statement (or is affected by [--moduleDetection force or auto](https://www.typescriptlang.org/tsconfig#moduleDetection)): and do not indicate any involvement of the "isolatedModules": true field.
Honestly I have not seen/found a better option to fix this inconvenience than how i addressed it with the PR #1469