2

I usually have the following code:

class Foo {
    foo: SomeType[];

    doSomething() {
        const a = this.foo = [];
    }
}

In this case, a would be any[] or never[] (depends on environment) instead of SomeType[]. If I specify noImplicitAny on those that imply any[], the compiler would throw an error.

I know the below cast fixes the problem, but why can't TypeScript deduce the type from this.foo?

        const a: SomeType[] = this.foo = []; // Have to repeat the type again

Reproducible code:

tsconfig.json:

{
    "compilerOptions": {
        "noImplicitAny": true
    }
}

test.ts:

class Foo {

    foo: number[];

    doSomething() {
        const a = this.foo = [];
    }

}

TypeScript complaint (at least in VS Code): enter image description here

10
  • I can't reproduce any such implicit any error; can you make sure you've got a minimal reproducible example that demonstrates what you're talking about? Commented Oct 23, 2021 at 3:44
  • @jcalz Hi, the code in my original question should work, but I added more details. Probably the problem is in VS Code only (I do know VS has this problem as well). In your playground, you don't have an error, but a is still never[], which is the main problem. Commented Oct 23, 2021 at 3:49
  • Can confirm from ts playgroud, a is type never[]...interesting playground Commented Oct 23, 2021 at 3:51
  • What version of TypeScript are you using? If the issue does turn out to be specific to a particular IDE (this is highly unlikely) then you should probably tag it for that IDE. I understand that never[] is also not desired, but until I can get reproducible behavior that both you and I agree is happening then I'm not inclined to spend a lot of effort on researching it. If you want to change the question to be about never[] that's fine; otherwise you should provide enough info for someone to reproduce it (the playground is also using --noImplicitAny so that's not the issue) Commented Oct 23, 2021 at 3:52
  • Okay, I clarified the question. The problem is not about noImplicitAny, it's about not getting the desired array type. Neither never[] nor any[] is good. Commented Oct 23, 2021 at 3:56

1 Answer 1

2

The type being inferred as any[] makes sense because Javascript is right-associative wrt the assignment operator.

See this question: Multiple left-hand assignment with JavaScript

This means that the expression:

const a = this.foo = [];

Is interpreted as:

this.foo = [];
const a = [];

As you can see, the type information isn't associated with empty array, so any[] is the most correct type.


You can prove this is in fact what is happening with a simple example:

let t: number;
const a = t = 5;

The inferred type for a would be the literal number 5, not number (which is the type for t).


It seems that the typescript playground may be wrong in this case, which is why many (including myself) are reporting never[] as the inferred type.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, I lean towards this explanation too. I am going to send an issue to TypeScript repo. Hopefully they allow this case to make our lives easier. Just that I work on code like this a lot and it's inconvenient to declare the types again.
Also the playground works correctly. If you turn off strictNullChecks, it would act like VS Code, i.e. compile error due to a being implicit any[].
@LukeVo good to know

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.