What is the reason for an optional object property being assigned the 'never' type?

I'm having trouble understanding the code snippet below:

interface Example {
    first?: number,
    second?: {
        num: number
    }
}

const example: Example = {
    first: 1,
    second: { num: 2 }
}

function retrieveValue<Object, Key extends keyof Object>(obj: Object, key: Key): Object[Key] {
    return obj[key]
}

let a = retrieveValue(example, 'first')   // Successfully compiles, type of a is number | undefined
let b = retrieveValue(example.second, 'num') // Argument of type '"num"' is not assignable to parameter of type 'never'.

In this scenario, a has a type of number | undefined, which is as expected. However, b is assigned the type never. Why does this happen? I would anticipate { num: number } | undefined instead.

What am I overlooking, and how can I modify the code for successful compilation?

Answer №1

This issue arises due to the usage of strictNullChecks, where optional fields are defined as OriginalType | undefined. Accessible members are limited to those common in the union, and since undefined has no members, it results in never.

If you define obj as obj: O | undefined | null, it eliminates null from O.

function prop<O, K extends keyof O>(obj: O | undefined | null, key: K): O[K] | undefined | null {
    return obj && obj[key]
}

let x = prop(test, 'one')   // number | null | undefined
let y = prop(test.two, 'n') // number | null | undefined

Alternatively, here is a version that avoids unnecessary introduction of null and undefined:

interface Test {
    one?: number,
    two?: {
        n: number
    }
    req: {
        n: number
    }
}

const test: Test = {
    one: 1,
    two: { n: 2 },
    req: { n: 2 }
}

function prop<O, K extends keyof Exclude<O, undefined | null>>(obj: O, key: K): Extract<O, undefined | null> | Exclude<O, undefined | null>[K]
function prop<K extends PropertyKey, V>(obj: Record<K, undefined | null | V>, key: K): V | undefined | null {
    return obj && obj[key]
}

let x = prop(test, 'one')   // number | undefined
let y = prop(test.two, 'n') // number | undefined
let z = prop(test.req, 'n') // number 

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the method for adding a document within an array that is nested within another document?

Apologies if the title seems complex... I struggled to find a better way to describe it. The scenario I am dealing with fits the following Schemes: Collection1: const mongoose = require('mongoose'); const itemSchema = mongoose.Schema({ _id: ...

Leveraging scanner-js within an Angular2 environment

Exploring ways to incorporate Scanner-JS into my Angular2 project, a tool I discovered while tinkering with the framework. Being a novice in Angular2, this question might be elementary for some. I successfully installed scanner-js via npm npm install sc ...

Creating reducers for a unique data type: A step-by-step guide

Today, I was working on enhancing a shopping website using React Typescript and Context API. My goal is to utilize React Reducers to manage the state of my Shopping Cart. I have custom Types defined for the Product type, which includes an Items Array and s ...

Struggling to access the 'payload' property of an undefined object? In TypeScript, you can easily bind and access JSON objects using *ngFor directive

I've been attempting to retrieve highscores from the server using node angular and making an http request. Although I successfully obtain the JSON file from the server, I am encountering difficulty accessing the fields for processing in the *ngFor lo ...

Finding the appropriate method to access a template variable reference in a designated row of an Angular Material table (Angular 7)

Currently, I am working on implementing a more intricate version of a behavior inspired by Angular Material's tutorials. In my simplified example, an Angular Material table is populated with data from a string array. The first column contains input fi ...

Guide on initializing a Redux toolkit state with an array of objects or local storage using TypeScript

Currently, I am attempting to set an initial state (items) to an array of objects or retrieve the same from localStorage. However, I am encountering the following error. Type 'number' is not assignable to type '{ id: string; price: number; ...

Dynamic rows in an Angular 2 Material data table

I'm currently working on dynamically adding rows to an Angular 2 Data Table ( https://material.angular.io/components/table/overview) by utilizing a service called "ListService". This service provides me with the columns ("meta.attributes") to be displ ...

The file functions/lib/functions/src/index.ts is missing, preventing the deployment of Cloud Functions

Whenever I attempt to deploy my Firebase cloud functions, I encounter the following error. Expected outcome: Successful deployment of functions. Error: Error: An issue occurred while reading functions/package.json: functions/lib/index.js is missing and ...

Utilizing the spread operator in Typescript interfaces: best practices

I have a react component that includes the spread operator operating on ...other and passed down to lower levels of the component. interface ButtonProps { colourMode: string; regular: boolean; buttonText: string; disabled?: boolean; iconSize?: st ...

Removing API request in React.js

My approach: deleteSample = () => { this.sampleService .deleteCall(this.props.id) .then((response) => { window.location.reload(false); }) .catch((error) => { console.log ...

Data not being retrieved by HTTP GET request

I encountered an issue with my API where I made three Get requests using the same function but different URLs to differentiate between them. However, even though the provider returns the data in steps, the page response function does not receive it and sho ...

The error TS2339 is indicating that there is no property called myProperty on the type SetStateAction<User>

I'm encountering a TypeScript error while working with React that's leaving me puzzled: <html>TS2339: Property 'subEnd' does not exist on type 'SetStateAction&lt;User&gt;'.<br/>Property 'subEnd' d ...

Struggling to reach the same level of bundle optimization with webpack + angular when compared to angular-cli

I am currently facing an issue with two Angular projects that I have. One is developed using angular-cli, while the other one is built with Webpack and utilizes @ngtools/webpack. Both projects are based on Angular 7.1.4 and @angular-devkit 0.13.5. The code ...

I have a Visual Studio 2019 solution that consists of two projects - one is an Angular project and the other is written in TypeScript. I have successfully configured

We are currently utilizing Visual Studio 2019 (not the VS Code version) for our project. Within this solution, we have multiple projects included. One of these projects contains Angular code that we compile using the traditional 'ng build' comma ...

Making an Angular POST request and then navigating to a new component

Hello, I am a beginner in Angular and struggling to make my code work. It seems like a basic functionality issue that I can't seem to figure out. My goal is to send a post request to my .NET core API to register a user, and once that is done, navigat ...

Why is it that when the form is submitted, the value becomes unclear?

This is a form with HTML and TypeScript code that I am working on. <form> <div class="form-group"> <input class="form-control" ([ngModel])="login" placeholder="Login" required> </div> <div class="form-group"> &l ...

The error message "Theme does not include property 'navHeight'" is indicating that the 'navHeight' property is not defined within the 'Theme' type. This issue occurs when using MUI v5 syntax with Types

When attempting to incorporate MUI with new props declared in the Interface inside the theme.ts file (as suggested by the MUI docs), I encountered the error mentioned above while theme.palette.primary.main does work. Despite trying various solutions like i ...

Is it necessary to use useCallback when executing a function from a child component?

Consideration should be given to using useCallback when ensuring referential equality during parent component renders. However, it's unclear if this is necessary in a scenario where the parent is dealing with a child function. import { ReactNode, useC ...

Retrieve objects from an array that contain a certain specified key

I am trying to extract the objects from All_reports that contain the key: comentarioAdmin. Currently, I am retrieving all reports from All_reports, but I only want the reports that have the key comentarioAdmin. Thank you! getReports() { this.Service.g ...

NestJS endpoint throwing a 500 error after submitting a post request

Struggling with sending post requests in NestJS as they are returning an error message: ERROR: An error occurred in POST /api/fraud-rules in 8ms... { "isError": true, "status": 500, "name": "InternalError", & ...