125
votes

This is similar to #40796374 but that is around types, while I am using interfaces.

Given the code below:

interface Foo {
  name: string;
}

function go() {
  let instance: Foo | null = null;
  let mutator = () => {
   instance = {
     name: 'string'
   };  
  };

  mutator();

  if (instance == null) {
   console.log('Instance is null or undefined');
  } else {
   console.log(instance.name);
  }
}

I have an error saying 'Property 'name' does not exist on type 'never'.

I don't understand how instance could ever be a 'never'. Can anyone shed some light on this?

Thanks in advance.

9
It's pretty clear from your code that the else would indeed never get evaluated. The compiler is smart enough to see it.Nitzan Tomer
This is an example, let me add some more code that shows it still has the issue.Ray Booysen
It's pretty clear from your code that the else would indeed never get evaluated. It isn't obvious at all nor there is a smart compiler. There is a dumb transpiler which deviates from the established practices. In C#, for instance, one can assign null to any object...Bozhidar Stoyneff
@BozhidarStoyneff, it is established but regrettable practice: en.wikipedia.org/wiki/Null_pointer#Historyrkuksin

9 Answers

77
votes

Because you are assigning instance to null. The compiler infers that it can never be anything other than null. So it assumes that the else block should never be executed so instance is typed as never in the else block.

Now if you don't declare it as the literal value null, and get it by any other means (ex: let instance: Foo | null = getFoo();), you will see that instance will be null inside the if block and Foo inside the else block.

Never type documentation: https://www.typescriptlang.org/docs/handbook/basic-types.html#never

Edit:

The issue in the updated example is actually an open issue with the compiler. See:

https://github.com/Microsoft/TypeScript/issues/11498 https://github.com/Microsoft/TypeScript/issues/12176

65
votes

if you write Component as React.FC, and using useState(),

just write like this would be helpful:

const [arr, setArr] = useState<any[]>([])
29
votes

I had the same error and replaced the dot notation with bracket notation to suppress it.

e.g.:

obj.name -> obj['name']
19
votes

This seems to be similar to this issue: False "Property does not exist on type 'never'" when changing value inside callback with strictNullChecks, which is closed as a duplicate of this issue (discussion): Trade-offs in Control Flow Analysis.

That discussion is pretty long, if you can't find a good solution there you can try this:

if (instance == null) {
    console.log('Instance is null or undefined');
} else {
    console.log(instance!.name); // ok now
}
7
votes

if you're receiving the error in parameter, so keep any or any[] type of input like below

getOptionLabel={(option: any) => option!.name}
 <Autocomplete
    options={tests}
    getOptionLabel={(option: any) => option!.name}
    ....
  />
1
votes

In my own case when I was initiating the array. I used:

selectedActors: any = [];

So it makes it "dynamic" at first

0
votes

In my case it was happening because I had not typed a variable.

So I created the Search interface

export interface Search {
  term: string;
  ...
}

I changed that

searchList = [];

for that and it worked

searchList: Search[];
0
votes

In my case (I'm using typescript) I was trying to simulate response with fake data where the data is assigned later on. My first attempt was with:

let response = {status: 200, data: []};

and later, on the assignment of the fake data it starts complaining that it is not assignable to type 'never[]'. Then I defined the response like follows and it accepted it..

let dataArr: MyClass[] = [];
let response = {status: 200, data: dataArr};

and assigning of the fake data:

response.data = fakeData;
0
votes

I was having problems with ? and !

This piece worked for me.

if (ref != null){
    if (ref.current != null)
        ref.current.appendChild(child);
}