solid-start icon indicating copy to clipboard operation
solid-start copied to clipboard

[Bug?]: The example in the docs doesn't seam to work.

Open RonenEizen opened this issue 1 year ago • 14 comments

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:

  1. Create an solid-start app using one of the templates
  2. Declare '@solidjs/start/server' within the global.d.ts file
  3. Try accessing event.locals.<SOMETHING> within a route function

Context 🔦

No response

Your environment 🌎

No response

RonenEizen avatar May 02 '24 20:05 RonenEizen

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 avatar May 02 '24 21:05 ryansolid

@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 avatar May 02 '24 22:05 RonenEizen

@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.

AirBorne04 avatar May 03 '24 12:05 AirBorne04

Oh.. hmm so this is a weird typescript-ism.. Lovely. Not sure what to do with this then.

ryansolid avatar May 03 '24 20:05 ryansolid

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.

AirBorne04 avatar May 04 '24 21:05 AirBorne04

I am personally fine with the workaround. Should I keep this issue? Or would you rather have it resolved?

RonenEizen avatar May 05 '24 03:05 RonenEizen

@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.

AirBorne04 avatar May 05 '24 11:05 AirBorne04

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 avatar May 12 '24 00:05 rmacfie

@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.

AirBorne04 avatar May 12 '24 13:05 AirBorne04

@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 avatar May 12 '24 17:05 rmacfie

@rmacfie can you share the test setup, i tried making the stated modifications but it does not work for me.

AirBorne04 avatar May 13 '24 05:05 AirBorne04

@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.

rmacfie avatar May 13 '24 18:05 rmacfie

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 avatar May 13 '24 18:05 rmacfie

@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 ImportMetaEnv and RequestEventLocals types. You can see the diff here: 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.

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 in tsconfig.json broke 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

AirBorne04 avatar May 19 '24 13:05 AirBorne04