Make specific attributes as non-compulsory in Typescript

Seeking a solution that can achieve the following:

type MakeOptional<T, U> = /* ... */;

interface A {
  foo: string;
  bar: number;
  baz: Date;
}

type AWithOptionalFoo = MakeOptional<A, 'foo'>;
// desired output: { foo?: string | undefined; bar: number; baz: number; }

type AWithOptionalBarAndBaz = MakeOptional<A, 'foo' | 'baz'>;
// desired output: { foo?: string | undefined; bar: number; baz?: Date | undefined; }

This is my attempt so far...

type MakeOptional<T, U> = { [P in keyof T]: P extends U ? T[P] | undefined : T[P] }

...however, the properties are marked as T | undefined instead of having them appear as (optional)? T | undefined.

Any suggestions to improve this?

Answer №1

If you want to extract the non-optional keys in TypeScript, you can utilize the combination of Pick and Exclude types. Then, intersect this result with a mapped type that makes the remaining keys optional by including a union with undefined.

type MakeOptional<T, U extends keyof T> = Pick<T, Exclude<keyof T, U>> & {
    [K in U]?: T[K] | undefined;
}

If you prefer not to have the undefined union in the optional keys, you can simply use the partial modifier instead:

type MakeOptional<T, U extends keyof T> = Pick<T, Exclude<keyof T, U>> & Partial<Pick<T, U>>

With either approach above, you can define your types as follows:

declare const test1: AWithOptionalFoo;
test1.foo // string | undefined
test1.bar // number
test1.baz // Date

// Note: The type defined here actually references "foo" and "baz".
declare const test2: AWithOptionalBarAndBaz;
test2.foo // string | undefined
test2.bar // number
test2.baz // Date | undefined

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

Visual Verification

I'm currently working on a NestJS application that serves images with authentication requirements. I have implemented JWT for authentication, but I encountered an issue when trying to display the image in an img tag because I cannot attach the Authori ...

Angular HTTP Patch method requires explicitly defined HTTP options as input parameters

I encountered a challenge with using Angular's HTTP patch method and noticed that the overloaded function patch(url, body, options) only accepts hardcoded values for HTTP options. An example of a hardcoded approach that works: patchEntity(id: number) ...

Modules can cause issues with Angular routing functionality

I am working on a management system that consists of multiple modules. The starting point for the application is the login-module. Upon successful login, the user is redirected to the main-module. From the main-module, users can navigate to other modules ...

Limit the type of parent to multiple children

Within my application, I have a main object defined with the following structure: type MainObject = { name: string; age: number; city: string; } Now, there is another section in the application that specifically makes use of the properties name, age ...

The Vue API client fetches necessary information from the server and generates a .csv file with accurate headers and IDs. However, the data retrieved is incomplete

Check out my code repository here: https://github.com/d0uble-happiness/discogsCSV App.vue <template> <div> <button @click="downloadSampleInputFile">Download basic sample file</button> </div> < ...

Error: Failed to execute close function in inappbrowser for Ionic application

Working on integrating the "in-app-browser" plugin with my Ionic project. Check out the code snippet below: const browser = this.iab.create(mylink, '_blank'); browser.on('loadstop').subscribe( data => { if ...

What could be causing Typescript Intellisense to not display Object extensions?

Let's take a look at this unique way to extend the Object type: interface Object { doSomething() : void; } Object.prototype.doSomething = function () { //perform some action here } With this modification, both of the following lines will c ...

The req.body parameter is consistently devoid of any content after being submitted

I recently switched to using a Typescript Fetch wrapper for my post and get requests, but I am facing an issue where I am getting an empty object on post requests (get requests work fine). This was not a problem when I was using Vanilla Js. My Nodejs code ...

Understanding how to leverage styles.module.scss for implementing personalized styling within react-big-calendar

I'm currently working with the react-big-calendar library in order to develop a customized calendar. However, I've encountered an issue where the SCSS styling is not being applied correctly. export const JobnsCalendar = () => ( <Calendar ...

What is the method for assigning a value to an attribute in HTML?

Is there a way to assign a function's value to an HTML attribute? For example, setting the attribute value to the value returned by the function foo. foo () : string { return "bar"; } I attempted the following without any success. <input type="b ...

Responsive Container MUI containing a grid

I am attempting to replicate the functionality seen on YouTube's website, where they dynamically adjust the grid layout based on the container size when a Drawer is opened or closed. Essentially, it seems that YT adjusts the grid count based on the c ...

Finding the key type in an interface

Here is a challenge... This is the code snippet from titleBarContainer.tsx: function TitleBarContainer() { const systemData = useSelector((state: RootState) => state.counter.systemData) const dispatch = useDispatch() const onChangeSystemDa ...

Activate the mat-menu within a child component using the parent component

Incorporating angular 6 along with angular-material, I am striving to trigger the matMenu by right-clicking in order to utilize it as a context menu. The present structure of my code is as follows. <span #contextMenuTrigger [matMenuTriggerFor]="context ...

Please define the minimum and maximum `tsc` versions in your tsconfig.json file

Can we dictate the specific version of typescript (tsc compiler) to use for compiling the project? { "compilerOptions": { "specificVersion": '', // ? "outDir": "dist", "strict": true ...

Having T extend Record<string, any>, the keyof T does not return 'string' as a type

My goal is to achieve the following: type UserDataProps<FieldName extends keyof DataShape, DataShape extends Record<string, any>> = { id: string; value: DataShape[FieldName]; } const userDataBuilder = <FieldName extends keyof DataShape, ...

Customize your Joi message using the .or() method

I'm attempting to personalize a message for the .or() function in Joi, similar to this: https://i.stack.imgur.com/68dKx.png The default message from Joi is as follows: Validation Error: "value" must contain at least one of [optionOne, optionTwo] ...

Troubleshooting a NextJs/TS problem with importing ESM modules

Click here for the Code Sandbox I'm currently in the process of transitioning some code to NextJS 11 / Webpack 5, including certain modules that now exclusively support ECMAScript Modules (esm). Prior to the upgrade, I could easily export all files ...

What steps can I take to resolve a dependency update causing issues in my code?

My program stopped working after updating one of the dependencies and kept throwing the same error. Usually, when I run 'ng serve' in my project everything works fine, but after updating Chartist, I encountered this error: An unhandled exception ...

Styling with react-jss based on intricate conditionals

After experimenting with react-jss for a few weeks, I am faced with the challenge of styling components efficiently. With numerous conditionals in these components, I am striving to avoid creating an excess of new components that essentially share the same ...

Webpack does not support d3-tip in its current configuration

I'm having some trouble getting d3-tip to work with webpack while using TypeScript. Whenever I try to trigger mouseover events, I get an error saying "Uncaught TypeError: Cannot read property 'target' of null". This issue arises because th ...