language-tools: TypeScript incorrectly considers variable as possibly null inside condition that checks variable
Describe the bug TypeScript error “Object is possibly null” is shown for nested conditional checks.
To Reproduce Simple test case:
<script lang="typescript">
interface TestObject {
author?: string;
}
export let test: TestObject | null;
</script>
{#if test}
<div>
{#if test.author}
<div>Author: {test.author}</div>
{/if}
</div>
{/if}
TypeScript throws error Object is possibly null
on line {#if test.author}
, not specifically on test
inside that line.
Expected behavior Expected not to throw any errors.
System (please complete the following information):
- OS: OSX 10.15.7
- IDE: VSCode
- Plugin/Package: “Svelte for VSCode”
Additional context
If nested conditional statement is removed and in TestObject interface author?
is replaced with author
(to make it required), it would be logical for TypeScript to throw the same error for {test.author}
, but it doesn’t. So looks like error is triggered by nested conditional statement, without it TypeScript knows that test
is not null.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 10
- Comments: 21 (13 by maintainers)
Commits related to this issue
- Transform if-blocks to ternaries #619 This way the TypeScript control flow will be broken in less instances and nested if-blocks like ``` {#if a} {#if a.a} .. {/if} {/if} ``` will not throw ... — committed to dummdidumm/language-tools by deleted user 4 years ago
- Transform if-blocks to ternaries (#696) #619 This way the TypeScript control flow will be broken in less instances and nested if-blocks like ``` {#if a} {#if a.a} .. {/if} {/if} ``` ... — committed to sveltejs/language-tools by dummdidumm 4 years ago
- (fix) if conditions control flow This adds an IfScope to svelte2tsx which keeps track of the if scope including nested ifs. That scope is used to prepend the resulting condition check to all inner la... — committed to dummdidumm/language-tools by deleted user 3 years ago
- (fix) if conditions control flow (#846) This adds two new scopes to svelte2tsx: IfScope, which keeps track of the if scope including nested ifs, and TemplateScope, which tracks all initialized variab... — committed to sveltejs/language-tools by dummdidumm 3 years ago
Small update/summary:
#await
,#each
,let:X
. This is due to the way we have to transform the code. We haven’t forgotten about this issue and are still looking for ways to solves this in a good way.Right now you can’t use typescript in markup. There’s no way to preprocess markup or let compiler parse typescript syntax. So non-null assertion is not possible. Haven’t tried the viability buy maybe we could copy the upper-level condition and append it before the nested condition
I’ve found an issue - This works correctly inside templates now, but not in event listeners. I’m not sure if I should open a new issue for it, but here’s a repro:
Thanks! I always assumed it was TS feature similar to non-null statement
foo!
. That makes it much simpler.Always learning something new 😃
if you mean optional chaining, that’s a new javascript feature, not just a typescript feature. It’s available in svelte after 3.24.0
A more pragmatic workaround for now would be
It’s quite annoying, especially when it’s not just drilling inside the same object but making separate conditions:
Strictly speaking the control flow was correct before these relaxing changes because one could modify other variables within an each loop or an await.
… but who does this? You can fabricate the same runtime errors in TS, too, btw. So it’s more of a tradeoff in DX than “this is 100% correct”.
But before we discuss this further in here, please take this discussion to #876 😄