Replies: 8 comments
-
Maybe we can use types to our advantage here and make it so that attempts to use function components will emit a helpful message in the type error. |
Beta Was this translation helpful? Give feedback.
-
💯 I was bit by this when I started learning and still am sometimes today. Seeing more errors for when I'm doing something wrong and requiring more explicitness on templating returns is a good tradeoff |
Beta Was this translation helpful? Give feedback.
-
To add to the alternative, we can make the error clearer, but never as clear as a "native" typescript error. The name of the missing key is in the error message, so if we named the symbol e.g.
We could go further and use a string, though I worry that someone somewhere would try and actually assign the property. That said I think outright removing it makes more sense. |
Beta Was this translation helpful? Give feedback.
-
This sounds good. The only thing I don't like is breaking changes in minor releases. I personally would go to 2.0, and then not hesitate to go to 3.0, 4.0, etc, as needed and organically without too many breaks at once. As a user I would prefer a clear migration guide for each breaking change, and I would also like less breaking changes at a time (more major bumps), so that I have a clear path, and so that the version numbers have real meaning. The worse is installing something in a project, then the next |
Beta Was this translation helpful? Give feedback.
-
I posted on Discord as well but I want to post here as well just for visibility. Unfortunately I don't keep up to date that frequently on updates here so wasn't aware of this change until just now. solid/packages/solid/src/render/flow.ts Line 141 in 57f4d51 Show , rely on an unsafe type cast. Either it works and should type-check, or it doesn't work, and shouldn't type-check. It shouldn't work and also not type-check (as now Show and any other component that uses control flow must now do).
My non-library website codebase now has 256 type errors to fix, all by adding this unsafe cast. It isn't just library authors that are affected by this change (although they are too), consider a simple component that just displays the min:sec until a target date/time: https://gitlab.com/_mike/kuachicups/-/blob/master/client/src/shared/ui/Time.tsx#L25 It doesn't want to affect HTML layout any more than it has to, so it just returns a I think adding a symbol to the export interface Memo<T> {
readonly [`
== solid-js error ==
====================
Functions must be wrapped in @createMemo@ to be renderable.
For more information see https://github.com/solidjs/solid/discussions/1554
`]: unique symbol;
(): T;
} |
Beta Was this translation helpful? Give feedback.
-
I've stumbled across a scenario similar to @mikeplus64's today in an end-user application, in my case for a context that returns localized string accessors for use by other components. My application needs to work with the WebKit webview bundled with Linux distributions, and trivially replacing occurrences of Adding the Can TypeScript definitions be honest first again, please? To be frank, the minor ergonomic improvements provided by this change won't do much for newbies. Debugging weird issues with bad error messages is the bread and butter of realistic JavaScript development anyway, and in this case the error message perhaps doesn't have to be that bad, as Mike pointed out. |
Beta Was this translation helpful? Give feedback.
-
Was there a work around for this: E.g. function MyComp(props) {
- return createMemo(() => props.count * 2)
+ return createFnElement(createMemo(() => props.count * 2))
} Then make
I suppose the issue is ensuring E.g.
Edit: Actually, that |
Beta Was this translation helpful? Give feedback.
-
I am quite happy with the return a fragment solution. There is not need to do the ugly typecasting anywhere, even when using a memo. function MyComp(props) {
- return createMemo(() => props.count * 2);
+ let x = createMemo(() => props.count * 2);
+ return <>{x()}</>;
} |
Beta Was this translation helpful? Give feedback.
-
Summary
This RFC looks for feedback on a change to restrict TypeScript JSX in a way that will make the journey better for most developers but make things more forced for advanced cases. By removing Function Element when and how to use functions in Solid's JSX would be greatly simplified, and produce much more idiomatic and predictable code.
Background
I have struggled with this forever and I realize a lot of it comes from my background of using both JavaScript in a very JavaScript way and having experienced in typed languages that are not TypeScript. Our types to the best of my efforts reflect everything that could be done with our syntax, but not what makes sense to do.
There are details in our runtime that we need to support but are confusing to developers as there are conditions where passing functions works as expected and others that don't. However, from a DSL design standpoint, we should only be passing functions that receiving JSX Element is expecting. This confusion has caused a number of issues submitted that are basically abusing a mechanism isn't intended.
Proposal
We remove
FunctionElement
from the JSX.Element types. This has several implications but I will show some of the most common ones.Authoring
First authoring components. You will not be able to return a function or Memo without casting it. So do that:
Or return a fragment
Usage
1. Functions as children JSX native elements now will error
This makes it much clearer from types that you should be calling signals as functions and that arbitrary functions inlined are not expected. The big plus of this is people coming from other non-signal frameworks will immediately understand they aren't in Kansas anymore and push them towards calling the function. Something already necessary for native prop bindings.
2. Component children/renderBodies will only expect function children if defined
This removes any expectations of just randomly passing functions to Components not expecting them.
Alternative
Instead of removing the Function Element give it a typescript unique symbol that would be implemented on Solid internals like our Accessor Type so it specifically allows Signals and Memos to be used directly. This removes the authoring burden. However, it produces less clear error messages complaining about missing symbols and it still allows for inconsistency in a number of places where you can pass a Signal directly versus a function.
Impact
This being part of the JSX types will impact every project once adopted. There will be new TS errors but no functionality will change. That being said this should mainly impact library authors and utilities, and can be solved with a backwards-compatible cast.
as unknown as JSX.Element
Adoption
Ideally since TypeScript itself has set the precedence I'd like to introduce this change in a minor version. Mostly likely 1.7. This puts us in a good place on semantics to support the migration to Solid 2.0 implementation updates.
Beta Was this translation helpful? Give feedback.
All reactions