Last updated: Feb 28, 2024
Reading timeยท5 min
If you got the error in React.js, click on the second subheading.
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.
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); }
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.
To solve the error, use square brackets instead of dot notation to access the property.
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']); }
We used bracket notation instead of dot notation which solved the error.
In short, do obj['myProperty']
, instead of obj.myProperty
.
You can also use a type assertion to get around the error.
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); }
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.
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); }
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.
Another cause of the error is declaring an empty array without assigning a type to it.
const obj = { years: [], }; // ๐๏ธ never[] console.log(obj.years);
If you declare an empty array, make sure to type it explicitly to avoid any confusing errors.
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:
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.
If you got the error when declaring an array state variable with the useState hook, use a generic to type the array.
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.
Here are some examples of how you would use more specific types when typing an array state variable.
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.
useRef
hook in React.jsYou might also get the error when using refs with the useRef hook.
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
.
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.
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.
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.
You can learn more about the related topics by checking out the following tutorials: