-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
breaking: add $bindable() rune to denote bindable props #10851
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
alternative to #10804
|
@@ -490,14 +490,24 @@ let { a, b, c, ...everythingElse }: MyProps = $props(); | |||
> | |||
> ...TypeScript [widens the type](https://www.typescriptlang.org/play?#code/CYUwxgNghgTiAEAzArgOzAFwJYHtXwBIAHGHIgZwB4AVeAXnilQE8A+ACgEoAueagbgBQgiCAzwA3vAAe9eABYATPAC+c4qQqUp03uQwwsqAOaqOnIfCsB6a-AB6AfiA) of `x` to be `string | number`, instead of erroring. | |||
|
|||
Props cannot be mutated, unless the parent component uses `bind:`. During development, attempts to mutate props will result in an error. | |||
By default props are treated as readonly, meaning reassignments will not propagate upwards and mutations will result in a warning. You will also get an error trying to `bind:` to them. To declare props as bindable, use [`$bindable()`](#bindable). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are reassignments also a warning, or do they just silently not work? It's also not clear to me here that these are dev-time-only warning (which I assume they are) - and I'm not clear on which things will result in a warning versus result in an error, and whether that's a runtime error/warning (I assume so) or a compile-time error/warning (I assume not, unless you're relying on types).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me know if the refined sentences are more clear.
packages/svelte/src/compiler/phases/3-transform/client/visitors/javascript-runes.js
Outdated
Show resolved
Hide resolved
Co-authored-by: Rich Harris <[email protected]>
* tweak error message for readonly rest props * remove property in prod * Update packages/svelte/src/internal/client/reactivity/props.js --------- Co-authored-by: Simon H <[email protected]>
@@ -490,14 +490,34 @@ let { a, b, c, ...everythingElse }: MyProps = $props(); | |||
> | |||
> ...TypeScript [widens the type](https://www.typescriptlang.org/play?#code/CYUwxgNghgTiAEAzArgOzAFwJYHtXwBIAHGHIgZwB4AVeAXnilQE8A+ACgEoAueagbgBQgiCAzwA3vAAe9eABYATPAC+c4qQqUp03uQwwsqAOaqOnIfCsB6a-AB6AfiA) of `x` to be `string | number`, instead of erroring. | |||
|
|||
Props cannot be mutated, unless the parent component uses `bind:`. During development, attempts to mutate props will result in an error. | |||
By default props are treated as readonly, meaning reassignments will not propagate upwards and mutations will result in a warning at runtime in development mode. You will also get a runtime error when trying to `bind:` to a readonly prop in a parent component. To declare props as bindable, use [`$bindable()`](#bindable). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In pure Markdown the link appears to work, in the generated docs the ID of the heading is $props-$bindable
, though, and this link is not adjusted.
All the links on the right side also generate this alert for when you navigate from the REPL to the docs:
Isn't this missing a changeset? |
You're right we missed that, but too late, next version is already out so we can only adjust the changelogs manually now |
Wouldn't that make bindable props optional though? How would you make them required? |
It does seem to change the default inference, not sure if that could be adjusted/fixed 🤔. Using types, properties can be explicitly marked as required/optional, though. /** @type {{
* req: string,
* notRequired?: string,
* }}*/
let {
req = $bindable(),
notRequired = $bindable(),
} = $props(); (Note the |
Alternative to / closes #10804
closes #10768
closes #10711
Initially I was against
let { prop = $bindable() } = $props()
because it felt too weird to use a default initializer as marking a prop as bindable. But after implementinglet { prop } = $props.bindable()
I experienced a couple of flaws of this approach which all come down to there now being two runes which take properties from the same bag:$props()
and$props.bindable()
...rest
parameter on the other prop, which then also includes that one property you destructured in the other one$props()
and$props.bindable()
have the same shape but there are no restrictions to actually type them that wayFueled by the weirdness I implemented the
let { prop = $bindable() } = $props()
which we initially rejected as a close second - and after actually writing the code instead of just thinking about it theoretically it actually feels much nicer than$props.bindable()
. The default assignment is a bit weird but I got used to it in no time. I therefore propose to go through with this variant.Before submitting the PR, please make sure you do the following
feat:
,fix:
,chore:
, ordocs:
.Tests and linting
pnpm test
and lint the project withpnpm lint