# Table of Contents
- Property does not exist on type 'never' in TypeScript
- 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 toaccess a property on a value of type never
or when TypeScript gets confusedwhen 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
Copied!
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 knowif (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 thesubheading:
- Property does not exist on type 'never' in React
The cause of the error is thatTypeScript gets confusedwhen 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 theproperty.
index.ts
Copied!
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 knowif (employee == null) { console.log('employee is nullish');} else { // ✅ Works fine now (Use bracket notation) console.log(employee['salary']);}
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
Copied!
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 knowif (employee == null) { console.log('employee is nullish');} else { // ✅ using a type assertion console.log((employee as Employee).salary);}
The code for this article is available on GitHub
Type assertions are used when we have information about the type of a value thatTypeScript can't know about.
We used a type assertion to set the type of the employee
variable toEmployee
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 theany
type.
index.ts
Copied!
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 knowif (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 ofany
.
The any
type effectively turns off type checking, so you are able to accessany property on the variable without getting a type-checking error.
You can also use a comment to disabletype checking.
# Don't declare empty arrays without typing them
Another cause of the error is declaring anempty array without assigning atype to it.
index.ts
Copied!
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 anyconfusing errors.
index.ts
Copied!
type Example = { years: number[];};const obj: Example = { years: [],};// ✅ number[]console.log(obj.years);
The three most common sources of thenever type in TypeScript are:
- having a conditional block that is never going to run, because it isimpossible 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 totype 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 theref value in your React application.
If you got the error when declaring an array state variable with theuseState hook, use a generic totype the array.
App.tsx
Copied!
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 morespecific types.
# Typing a State array in React
Here are some examples of how you would use more specific types whentyping an array state variable.
App.tsx
Copied!
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 onhow 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 theuseRef hook.
App.tsx
Copied!
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
Copied!
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 areassigning 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 outthe following article.
The type of the ref
could be an object or whatever suits your use case.
App.tsx
Copied!
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 whattype of value we will eventually assign to it.
Notice that we're also using theoptional chaining (?.) operator.TypeScript doesn't know if we're going to assign a value to the ref
, or if weare 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 youforgot 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 likelywith generics if using React hooks.
# Additional Resources
You can learn more about the related topics by checking out the followingtutorials:
- Argument of type not assignable to parameter type 'never'
- Disable type checking for a File or a Line in TypeScript
- How to push an Element into a state Array in React
- Remove an Element from state Array in React
- Property does not exist on type '{}' in TypeScript [Solved]