language-tools icon indicating copy to clipboard operation
language-tools copied to clipboard

Better type safety for two way binding

Open probablykasper opened this issue 3 years ago • 12 comments

Describe the bug

There's no svelte-check error when binding to a property if the property is a broader type.

To Reproduce

<script lang="ts">
  import MyComponent from './MyComponent.svelte'
  let value: Date
  $: console.log('value:', value)
</script>

<MyComponent bind:value />

MyComponent.svelte:

<script lang="ts">
  export let value: Date | null = null
</script>

{JSON.stringify(value)}

Expected behavior

There should be a type error because value is defined as Date even though it can also be null

System

  • OS: macOS
  • IDE: VSCode
  • Plugin/Package: "Svelte for VSCode", svelte-check, svelte2tsx

probablykasper avatar Feb 19 '22 01:02 probablykasper

This works as expected. Date | null means "you can pass one of the two types in here", so Date is correct. If it's about JSON.stringify not throwing an error: you probably didn't turn on strict mode in your tsconfig.

dummdidumm avatar Feb 19 '22 08:02 dummdidumm

Ah wait, do you mean that, because it's a binding, this should check both ways, i.e. that Date | null is also assignable to Date?

dummdidumm avatar Feb 19 '22 08:02 dummdidumm

Yes. Even though we define value as Date, the value ends up being null

probablykasper avatar Feb 19 '22 17:02 probablykasper

Implementation notes:

  • only do this for the new transformation
  • We need to assign both ways: the variable as an input to the component, the component instance's prop to the variable. Since we can't assign the component to the property since we assign the property to the component during its construction, we also can't have built-in mappings and therefore need to transfer the error in one case to the correct position somehow - maybe through another comment pragma. Code could look something like this: const component = new Component({..., props: {...binding: variable});/* mapMeToX */variable = component.$$prop_def.binding/* endMapMeToX */

dummdidumm avatar Feb 20 '22 10:02 dummdidumm