Skip to content
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

TypeScript incorrectly considers variable as possibly null inside condition with array index access #1541

Open
KuSh opened this issue Jun 30, 2022 · 3 comments
Labels
bug Something isn't working upstream

Comments

@KuSh
Copy link

KuSh commented Jun 30, 2022

Describe the bug

TypeScript error "Object is possibly 'undefined' ts(2532)" is shown for nested conditional checks.
This is a special case of fixed #619

Reproduction

<script lang="ts">
  export let content: {
    list: {
      image?: {
        src: string;
        alt: string;
      };
    }[];
  };
  export let item = 0;
</script>

<div>
  {#if content.list[item]?.image}
    <img
      src={content.list[item].image.src}
      alt={content.list[item].image.alt}
    />
  {/if}
</div>

Expected behaviour

No error should be thrown

System Info

Dependencies versions:

"svelte": "^3.48.0",
"svelte-check": "^2.7.2",
"svelte-preprocess": "^4.10.7",
"tslib": "^2.4.0",
"typescript": "^4.7.4"

and

Svelte for VS Code v105.18.1

Which package is the issue about?

svelte-check

Additional Information, eg. Screenshots

No response

@KuSh KuSh added the bug Something isn't working label Jun 30, 2022
@dummdidumm
Copy link
Member

This is a TypeScript limitation due to the array index access, so there's nothing we can do about it. You get the same error in a regular TS file:

let content: {
	list: {
		image?: {
			src: string;
			alt: string;
		};
	}[];
} = null as any;
let item = 0;

if (content.list[item]?.image) {
	content.list[item].image.src; // <- error
}

@dummdidumm dummdidumm changed the title TypeScript incorrectly considers variable as possibly null inside condition that checks variable TypeScript incorrectly considers variable as possibly null inside condition with array index access Jun 30, 2022
@KuSh
Copy link
Author

KuSh commented Jun 30, 2022

Hi @dummdidumm, thanks for your answer

The difference is that in TypeScript I can mark them as defined ;)

if (content.list[item]?.image) {
	content.list[item]!.image!.src; // <- no error
}

But this is not possible in the markup.
I have used another workaround where I store the indexed access in a variable in the code and check that variable instead of the array in the markup 👍

@ivanhofer
Copy link
Contributor

Having a similar problem:

<script lang="ts">
	import List from '$components/forms/List.svelte'

	type Item = { key: string; value: string }

	export let items: Item[]
</script>

<List bind:items let:index>
	{#if items[index]} <!-- this check has no effect on the type -->
		<!-- Error: Object is possibly 'undefined'. -->
		<input bind:value={items[index].key} />
	{/if}
</List>

I would expect that:

  1. the if check would work like it does in regular TypeScript code
    items[12].key // Error
    
    if (items[12]) {
    	items[12].key // no Error
    }
  2. we can use the ! operator inside the markup to tell the compiler "I know what I do"
    items[12]!.key // no Error in TypeScript
    <input bind:value={items[index]!.key} /> <!-- Error: Expected }-->

Becasue of the two-way-binding in a loop I can't really store the value in a variable and mark it as defined inside the script tag.

Current workaround:
Instead of marking the items as an array, make them a dynamic tuple with at least a single fixed item.
Then I can cast the index to the fixed value 0 and I can get rid of the error.

<script lang="ts">
	import List from '$components/forms/List.svelte'

	type Item = { key: string; value: string }

	export let items: [Item, ...Item[]] // `tuple` instead of `array`

	const typedAs0 = (value: number) => value as 0 // cast to fixed value `0`
</script>

<List bind:items let:index>
	{#if items[index]}
		<input bind:value={items[typedAs0(index)].key} />
	{/if}
</List>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working upstream
Projects
None yet
Development

No branches or pull requests

3 participants