solidjs / solid-start

SolidStart, the Solid app framework
https://start.solidjs.com
MIT License
5.05k stars 377 forks source link

[Bug?]: Miss classification from typescript #1613

Open ANDREA-1720 opened 2 weeks ago

ANDREA-1720 commented 2 weeks ago

Duplicates

Latest version

Current behavior 😯

When calling a function with inside "use server", it always returns a promise, but typescript set the type to the one of the return, causing the IDE to mark a type error

EXAMPLE CODE:

import { createSignal } from "solid-js";

function test(toLog: string) {
  "use server";
  console.log(toLog);
  return "pressed"
}

export default function Example() {
  const [text, setText] = createSignal("TEST")
  return (
    <button type="button" class="text-white" onClick={() => test("test").then((text: string) => {console.log(text)})}>
      { text() }
    </button>
  );
}

ERROR:

Property 'then' does not exist on type 'string'. ts(2339)

RESULT: The code perfectly work

Expected behavior 🤔

When calling a function with inside "use server", it always returns a promise, and TypeScript know that

EXAMPLE CODE:

import { createSignal } from "solid-js";

function test(toLog: string) {
  "use server";
  console.log(toLog);
  return "pressed"
}

export default function Example() {
  const [text, setText] = createSignal("TEST")
  return (
    <button type="button" class="text-white" onClick={() => test("test").then((text: string) => {console.log(text)})}>
      { text() }
    </button>
  );
}

NO ERROR:

RESULT: The code perfectly work

Steps to reproduce 🕹

Steps:

  1. bun create solid selecting to use typescript, with solidStart
  2. Write the example code
  3. bun dev

EXAMPLE CODE:

import { createSignal } from "solid-js";

function test(toLog: string) {
  "use server";
  console.log(toLog);
  return "pressed"
}

export default function Example() {
  const [text, setText] = createSignal("TEST")
  return (
    <button type="button" class="text-white" onClick={() => test("test").then((text: string) => {console.log(text)})}>
      { text() }
    </button>
  );
}

Context 🔦

No response

Your environment 🌎

System:
    OS: macOS 14.5 23F79 arm64
    CPU: (8) arm64

Binaries:
    Bun: 1.1.24 - /Users/andrea/.bun/bin/bun
npmPackages
    "@solidjs/router": "^0.14.1",
    "@solidjs/start": "^1.0.6",
    "autoprefixer": "^10.4.19",
    "postcss": "^8.4.38",
    "solid-js": "^1.8.18",
    "tailwindcss": "^3.4.3",
    "vinxi": "^0.4.1"
ANDREA-1720 commented 2 weeks ago

Actually the code was supposed to look like, but the result is the same, it is only easier to see that the function test() runs only on the server :

import { createSignal } from "solid-js";

function test(toLog: string) {
  "use server";
  console.log(toLog);
  return "pressed"
}

export default function Example() {
  const [text, setText] = createSignal("TEST")
  return (
    <button type="button" class="text-white" onClick={() => test("test").then((text: string) => {setText(text)})}>
      { text() }
    </button>
  );
}
Brendonovich commented 2 weeks ago

It's kinda expected that you define all use server functions as async function or const ... = async () =>, getting typescript to help here would probably require a plugin

ANDREA-1720 commented 2 weeks ago

I understand, it can be kinda unintuitive though. I think that one solution may be to either force a function with "use server" in it to be asynchronous, or maybe make the non asynchronous one to do not return a Promise, but directly the returned value (I understand both of these are, possibly, breaking changes... but I think these options are far more intuitive than the current implementation)