-
-
Notifications
You must be signed in to change notification settings - Fork 200
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
Property with an initial default value can get a undefined excluding TypeScript type while still becoming undefined during runtime #2236
Comments
This is the same as sveltejs/svelte#9948 but about Svetle 4 |
The main problem is, that most people expect and think, this is a default value (like function default value). And because a lot of people think so (and if they do not know this issue) - here are potentially many svelte apps/sites that can break - any time, if not tested well. Svelte 4 is based on classes (I think), so this makes more sense... I don't know if this could be changed. Svelte 5 have a chance to make it right. I hope for this - really! Today... you have only this 2 ways to WORKAROUND it (and it is very svelte unlike!)
or... more hard-coded
|
Thanks for these quick replies. To be clear: this issue is not about Svelte's weird initial prop behavior. I understand that this is non negotiable at this point. This issue is about enforce an appropriate TypeScript type to represent this weird behavior. I believe this will go a long way in mitigating the resulting risks. I for one would have certainly found this Svelte issue way earlier, if TypeScript had complained. The type of any prop with an initial (a.k.a. default) value must always include Of course even better would be appropriate narrowing, if the developer actually sets a real default via <script lang="ts">
// It should be required to do this:
export let propWithInitalValue: string | undefined = "inital value"
// currently propWithInitalValue: string is accepted by TypeScript which
// allows invalid programms to pass type checking.
// This should continue to work:
export let propWithRealDefault: string;
$: propWithRealDefault ??= "default value";
</script> |
I am not sure if you understand the linked language-tools issue correctly. The problem mentioned there is that: In exactOptionalPropertyTypes: true exactOptionalPropertyTypes: false |
I hope I understood that correclty @jasonlyu123. You are concerned with the following scenario: Given a <script lang="ts">
export let prop: string = "inital value"
$: () => {
if (prop === undefined) {
// Dead code, as prop is always a string. Thanks, TypeScript
destroyTheWorld()
}
}
</script> A <script lang="ts">
import Component from './Component.svelte'
</script>
<Component prop="A real value" />
<Component />
<!-- the following must be an error, as it would destroyTheWorld() -->
<Component prop={undefined} /> Explicitely setting The idea behind this is to guarantee Unfortunetely, this does not work: Consider this <script lang="ts">
import Component from './Component.svelte'
let counterExample: { prop?: string } = { prop: "defined" }
</script>
<Component {...counterExample} />
<button on:click={() => {
// nothing to complain here:
counterExample = {}
}
}>Break gurantee!</button> So, within our |
Let's wait with proceeding this until we have decided if we want to switch the default behavior in Svelte 5. |
Is there an update on this issue now that Svelte 5 is further along in it's implementation? |
Honestly, I would say this is more than just an annoyance. When you're just working on your own code, it's an annoyance. When you're working with libraries that aren't aware of this issue, it's a proper minefield. Could I go in and submit a PR for everything I come across? Sure. But I'm sure that 99% of the issues are because Svelte made a choice that is unwise in retrospect. https://svelte.dev/repl/b71c5df8c24c4221a1c8b13184455375?version=3.46.6 |
My "solution" today is:
|
Svelte 5 will use the fallback value everytime the prop becomes undefined, therefore closing |
This issue was explicitly not about Svelte 4's default behaviour but about the language-tools wrong TypeScript type within a component. I don't get what this - certainly laudable - change in Svelte 5 fixes about this issue? |
Because the runtime behavior in Svelte 5 using the |
I got this. However: Svelte 5 is not released. Svelte 4 or even 3 codebases are pretty much a thing, and IMHO will be for quite a while. Nothing has changed for them regarding this issue. If the reason for closing is that language-tools wont support anything less than svelte 5 anymore, this should be at least closed as wontfix instead of completed. Otherwise it's very misleading. |
It's closed as in fixed in Svelte 5. We won't/can't backport this as changing this would be a breaking change |
I feel, as the OP of this issue, it should have some weight, when I say, that this is not resolved. Of course, it's your project and you are free to close any issue you want even without actually adressing them. With Svelte 5 this issue might not exist anymore, but it's certainly not fixed. Tbc: As explicitely stated earlier this issue is not with the weird behaviour around default values that Svelte <5 exhibits, but about the language tools using wrong types in many svelte projects. Having the right types in Svelte 5 projects is cool, but not a fix. But yaeh, I will not continue to argue any further. It is what it is. |
As stated earlier, this would be a huge breaking change (many people's projects would be littered with type errors), which is why we're not fixing this for Svelte 4. |
Describe the bug
According to sveltejs/svelte#4442 props' default values are really initial values as they are only used when a component is first created. While I consider this, as well as others who've created issues bevore me, to be a rather unintuitive design decision, I assume there to be good reasons for it.
However, after spending over half a day tracking down this issue from an obscure exception thrown in a production app, I think it remains at least a bug in Svelte's TypeScript implementation. We were able to type an optional property that had an initial value with a type that excludes
undefined
. However, the value of that property may very much becomeundefined
during runtime.To be specific, I belive I should not be able do this:
This is essentially a loaded footgun.
While I rate this as an annoyance, I cannot stress enough how much this defeats the core reason we use TypeScript in the first place.
If this will not be fixed, are there some ways to automatically prevent such flawed uses, i.e. intital values when they really should be a default?
This exact problem has been described in a comment before, as well in this issue in sveltejs language-tools. The reason to close the latter, is pretty murky to me.
Reproduction
This is a short repro simplified from our use case, unfortunately the repl does not support TypeScript. https://svelte.dev/repl/1448697c1adc4f31b658f5207747dece?version=3.29.4
Logs
No response
System Info
Severity
annoyance
The text was updated successfully, but these errors were encountered: