What is the best way to create a versatile object that can encompass any of the properties belonging to type T?

Here is a code snippet showcasing a sample function. The objective is to create a generic IncompleteVariant that mirrors the properties of T, but with all properties potentially unset.

The idea behind IncompleteVariant<T> is that it should essentially be an empty object like {}.

/**
 * Modifies the passed `newState` to fallback on the `initialState` if any property is not set.
 */
export function orInitialState<T extends object> (newState: IncompleteVariant<T>, initialState: T): T {
  type Key = keyof T;
  if(!newState) return initialState;
  const newerState: T = {...initialState}
  for(const key of Object.keys(initialState)) {
    if(newState.hasOwnProperty(key as Key)) newerState[key as Key] = newState[key as Key]
  }
  return newerState;
}

How can I define IncompleteVariant<T>? My attempted solution so far has been:

/**
 * Generic of object T but with all properties as optional.
 */
export type IncompleteVariant<T> = NonNullable<Partial<T>>

However, this results in the error message:

Type 'T[keyof T] | undefined' is not assignable to type 'T[keyof T]'. Type 'undefined' is not assignable to type 'T[keyof T]'.ts(2322)

Answer №1

Here is a revised function that addresses the issue:

    export function orInitialState<T extends object> (newState: Partial<T>, initialState: T): T {
        type Key = keyof T;
        if (!newState) return initialState;
        const newerState: T = { ...initialState };
        for (const key of Object.keys(initialState)) {
            if (newState.hasOwnProperty(key as Key)) {
                const nskv = newState[key as Key];
                if (nskv !== undefined && nskv !== null) {
                    newerState[key as Key] = nskv;
                }
            }
        }
        return newerState;
    }

The mistake does not lie in the InvariantType<T>, and there is no need for it to be NonNullable<> since T extends object.

It should not be assumed that

newState.hasOwnProperty(key as Key)
means
newState[key as Key] !== null | undefined
.

For example,

{ a: undefined }.hasOwnProperty("a")
returns true, but { a: undefined }["a"] is clearly undefined.

The same applies when using null instead of undefined.

Edit:

If you are concerned about these "undefined vs non-existent properties," consider looking into the compiler option found here: https://www.typescriptlang.org/tsconfig#exactOptionalPropertyTypes

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

Encapsulate the module function and modify its output

I am currently utilizing the node-i18n-iso-countries package and I need to customize the getNames function in order to accommodate a new country name that I wish to include. At the moment, I am achieving this by using an if-else statement like so: let cou ...

A guide to finding the mean in Angular by utilizing JSON information

import { Component, OnInit } from "@angular/core"; import { MarkService } from "../app/services/marks.service"; @Component({ selector: "app-root", templateUrl: "./app.component.html", styleUrls: ["./app.component.scss"] }) export class AppComp ...

Issues with the md-radio-button not functioning properly in Angular 2

I'm in need of two radio buttons to choose between two options. Here's the code I'm using: <md-radio-button [value]=true [(ngModel)]="carSelected" name="carOption">Car</md-radio-button> <md-radio-button [value]=false [(ngMode ...

Is it feasible to mock a defined function in Typescript for a unit test scenario?

Currently, I am working on typescript code that compiles into javascript, gets bundled with rollup, and is utilized by a framework. This framework exposes a library to me in the global scope, taking the form of a function: fun({ prop1: number, ...

Creating UI Bootstrap dropdowns using ng-repeat on the fly

As a newcomer to AngularJS and UI Bootstrap, I am facing an issue with adding dropdowns dynamically using ng-repeat. The main problem lies in the fact that when one dropdown is clicked, it triggers all of them simultaneously. It seems like there is some mi ...

Struggled with setting up the WebSocket structure in typescript

Issue Running the code below results in an error: index.tsx import WebSocket from 'ws'; export default function Home() { const socket = new WebSocket('ws://localhost:1919/ws'); return ( <div>Home</div> ); } ...

Tips for minimizing disagreements while implementing optional generic kind in TypeScript?

An issue arises in StateFunction due to its optional second generic type that defaults to a value. Even when omitting this second generic, undefined still needs to be passed as an argument, which contradicts the idea of it being optional. While making arg ...

ag-grid-angular failing to present information in a table layout

I have implemented ag-grid-angular to showcase data in a structured table format, but the information appears jumbled up in one column. The data for my ag-grid is sourced directly from the raw dataset. https://i.stack.imgur.com/sjtv5.png Below is my com ...

Tips for monitoring dispatch in fetch/middleware functions

Just testing a basic webpage <template> <HomeTemplate /> </template> <script lang="ts"> import Vue from 'vue' export default Vue.extend({ async fetch(context) { // or middleware(context) await context.store.disp ...

Reconfigure an ancestral item into a designated key

I have a single object with an array of roles inside, and I need to transform the roles into an array of objects. See example below: Current Object: displayConfiguration: { widgetList: { widgetName: 'widget title', entityType: 'As ...

The presence of React Router in Office JS Excel results in a blank screen

My current project involves developing add-ins for Excel using TypeScript and React. However, I have encountered numerous challenges along the way. Unlike a typical CRA React boilerplate web application, the Office add-in behaves differently. To illustrate ...

Validation of time input in Angular7 using reactive forms with Material design

Dealing with an angular 7 reactive form, the input field in this form allows users to view and modify time. The issue arises when users enter nonsensical numbers in this field that do not align with valid time ranges (e.g., hours should be between 1-24, mi ...

Clearing the filename in a file type input field using React

When using this input field, only video files are accepted. If any other types of files are uploaded by enabling the "all files" option, an alert will be displayed. While this functionality is working correctly, a problem arises if a non-video file is adde ...

tips for preventing issues when the data array is empty

Here is the JSON data that I am dealing with: { "id": 43, "dataEvento": "2022-09-01T00:00:00.000+0000", "dataInvio": null, "idComunicazioneAssociata": null, "certificatoMedico" ...

Implementing a THREE.PerspectiveCamera object within the setState method in react.js

In my current project, I am utilizing both three.js and react.js. Presently, I am instantiating a THREE.PerspectiveCamera object in the following manner. init = () => { this.state.camera = new THREE.PerspectiveCamera(25, window.innerWidth / window. ...

What is the process for utilizing a variable as a string or object in TypeScript?

Consider the scenario where a variable may hold either a string or an object with properties like this: value?: string | { name: string, type: string } Attempting to work with it below leads to a compile error: console.log(value?.name || value) console.lo ...

Converting a file into a string using Angular and TypeScript (byte by byte)

I am looking to upload a file and send it as type $byte to the endpoint using the POST method My approach involves converting the file to base64, and then from there to byte. I couldn't find a direct way to convert it to byte, so my reasoning may be ...

Encountering an Error on Building Android with Ionic 2 RC0 and Angular 2: ngc error during symbol values resolution

An error occurs when trying to build the Android application using the command ionic build android. The error message reads: "ngc: Error: Error encountered resolving symbol values statically. Reference to a local (non-exported) symbol 'dictionary&apo ...

Discovering the power of Angular 2 with ngrx while putting my Reducer to the

Within my Reducer file: case PumpActionTypes.EnterLocalMode: return commandOne.upsertOne( {id: action.payload.id, changes: { local: false }}, state ); When testing, I aim to verify that the local property is indeed modified to false. My curr ...

Exploring the process of dynamically updating a form based on user-selected options

I need assistance with loading an array of saved templates to be used as options in an ion-select. When an option is chosen, the form should automatically update based on the selected template. Below is the structure of my templates: export interface ...