Property does not exist on type 'never' in TypeScript

avatar
Borislav Hadzhiev

Last updated: Feb 28, 2024
5 min

banner

# Table of Contents

  1. Property does not exist on type 'never' in TypeScript
  2. Property does not exist on type 'never' in React

If you got the error in React.js, click on the second subheading.

# Property does not exist on type 'never' in TypeScript

The error "Property does not exist on type 'never'" occurs when we try to access a property on a value of type never or when TypeScript gets confused when analyzing our code.

To solve the error, use square brackets to access the property, e.g. employee['salary'].

Here is an example of how the error occurs.

index.ts
type Employee = { salary: number; }; let employee: Employee | null = null; function setEmployee() { employee = { salary: 100 }; } setEmployee(); // ๐Ÿ‘‰๏ธ employee.salary is equal to 100 here // but TypeScript doesn't know if (employee == null) { console.log('employee is nullish'); } else { // โ›”๏ธ Error: Property 'salary' does not // exist on type 'never'.ts(2339) console.log(employee.salary); }

property does not exist on type never

If you get the error when using React.js, click on the link to scroll to the subheading:

The cause of the error is that TypeScript gets confused when analyzing our code.

# Use square brackets instead of dot notation to access the property

To solve the error, use square brackets instead of dot notation to access the property.

index.ts
type Employee = { salary: number; }; let employee: Employee | null = null; function setEmployee() { employee = { salary: 100 }; } setEmployee(); // ๐Ÿ‘‰๏ธ employee.salary is equal to 100 here // but TypeScript doesn't know if (employee == null) { console.log('employee is nullish'); } else { // โœ… Works fine now (Use bracket notation) console.log(employee['salary']); }

use square brackets instead of dot notation to access the property

The code for this article is available on GitHub

We used bracket notation instead of dot notation which solved the error.

In short, do obj['myProperty'], instead of obj.myProperty.

# Using a type assertion to solve the error

You can also use a type assertion to get around the error.

index.ts
type Employee = { salary: number; }; let employee: Employee | null = null; function setEmployee() { employee = { salary: 100 }; } setEmployee(); // ๐Ÿ‘‰๏ธ employee.salary is equal to 100 here // but TypeScript doesn't know if (employee == null) { console.log('employee is nullish'); } else { // โœ… using a type assertion console.log((employee as Employee).salary); }

using type assertion to solve the error

The code for this article is available on GitHub

Type assertions are used when we have information about the type of a value that TypeScript can't know about.

We used a type assertion to set the type of the employee variable to Employee so we can access the salary property in the else block.

If you want to turn off type checking to be able to access any property, use the any type.

index.ts
type Employee = { salary: number; }; let employee: Employee | null = null; function setEmployee() { employee = { salary: 100 }; } setEmployee(); // ๐Ÿ‘‰๏ธ employee.salary is equal to 100 here // but TypeScript doesn't know if (employee == null) { console.log('employee is nullish'); } else { console.log((employee as any).salary); }

turn off type checking to access any property using any type

The type assertion in the example sets the employee variable to have a type of any.

The any type effectively turns off type checking, so you are able to access any property on the variable without getting a type-checking error.

You can also use a comment to disable type checking.

# Don't declare empty arrays without typing them

Another cause of the error is declaring an empty array without assigning a type to it.

index.ts
const obj = { years: [], }; // ๐Ÿ‘‡๏ธ never[] console.log(obj.years);
The code for this article is available on GitHub

If you declare an empty array, make sure to type it explicitly to avoid any confusing errors.

index.ts
type Example = { years: number[]; }; const obj: Example = { years: [], }; // โœ… number[] console.log(obj.years);

The three most common sources of the never type in TypeScript are:

  • having a conditional block that is never going to run, because it is impossible for the condition to be met
  • the return type of a function that throws an error
  • TypeScript getting confused when analyzing our code
Want to learn more about typing arrays in TypeScript? Check out these resources: How to add Elements to an Array in TypeScript,Define an Array with Multiple types in TypeScript.

# Property does not exist on type 'never' in React

The error "Property does not exist on type 'never'" occurs when we forget to type a state array or don't type the return value of the useRef hook.

To solve the error, use a generic to explicitly type the state array or the ref value in your React application.

property does not exist on type never

If you got the error when declaring an array state variable with the useState hook, use a generic to type the array.

App.tsx
import {useState} from 'react'; function App() { // ๐Ÿ‘‡๏ธ use generic to type the state array const [arr, setArr] = useState<any[]>([]); return ( <div className="App"> <div>Hello world</div> </div> ); } export default App;

The example uses the very broad any type, but the concept applies to more specific types.

# Typing a State array in React

Here are some examples of how you would use more specific types when typing an array state variable.

App.tsx
import {useState} from 'react'; function App() { // ๐Ÿ‘‡๏ธ type it as string[] const [strArr, setStrArr] = useState<string[]>([]); // ๐Ÿ‘‡๏ธ type it as object array const [objArr, setObjArr] = useState<{name: string; age: number}[]>([]); return ( <div className="App"> <div>Hello world</div> </div> ); } export default App;

If you don't explicitly type the array, it implicitly gets a type of never[], which is effectively an array that will always be empty.

I've also written a detailed guide on how to type useState as an array or object.

# Explicitly typing the useRef hook in React.js

You might also get the error when using refs with the useRef hook.

App.tsx
import {useEffect, useRef} from 'react'; const ComponentA = () => { const inputRef = useRef(null); useEffect(() => { // โ›”๏ธ Error: Property 'focus' does not exist on type 'never'.ts(2339) inputRef.current?.focus(); }, []); return ( <div> <input ref={inputRef} /> </div> ); };

To solve the error, use a generic to explicitly type the ref.

App.tsx
import {useEffect, useRef} from 'react'; const ComponentA = () => { // ๐Ÿ‘‡๏ธ type the ref as HTML input element const inputRef = useRef<HTMLInputElement>(null); useEffect(() => { // โœ… Works now inputRef.current?.focus(); }, []); return ( <div> <input ref={inputRef} /> </div> ); };

We used a generic to type the ref as an HTMLInputElement because we are assigning the ref to an input element in the example.

Your type is likely going to be different. If it's a different HTML element, their names are consistent, e.g. HTMLDivElement, HTMLSpanElement, etc.

You can also hover over any JSX element and read its type.

If you get the error useRef "Object is possibly null", check out the following article.

The type of the ref could be an object or whatever suits your use case.

App.tsx
import {useRef} from 'react'; const ComponentA = () => { const inputRef = useRef<{name: string}>(null); console.log(inputRef.current?.name.toUpperCase()); return ( <div> Hello World </div> ); };

This is necessary because if we don't type the ref, TypeScript can't know what type of value we will eventually assign to it.

Notice that we're also using the optional chaining (?.) operator. TypeScript doesn't know if we're going to assign a value to the ref, or if we are going to assign it to an HTML element like in the previous examples.

If you get the "Property does not exist on type 'never'" error, chances are you forgot to explicitly type a value and it implicitly got assigned a never type.

To debug this, hover over the value and look for ways to type it - most likely with generics if using React hooks.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev