What is the process for generating a new type that includes the optional keys of another type but makes them mandatory?

Imagine having a type like this:

type Properties = {
    name: string
    age?: number
    city?: string
}

If you only want to create a type with age and city as required fields, you can do it like this:

type RequiredFields = RequiredOptional<Properties>

This will give you:

type RequiredFields = {
    age: number
    city: string
}

Is this achievable and how?


I have come across solutions (such as this) on extracting optional keys from a type, but not exactly what I am looking for. The closest I've got is:

type OptionalKeysOfType<T extends object> = keyof {
    [K in keyof T as T extends Record<K, T[K]> ? never : K]: K
}
type RequiredFields = {
    [key in OptionalKeysOfType<Properties>]: NonNullable<Properties[key]>
}

However, this method has two issues:

  1. It's not very generic
  2. The displayed keys in VSCode/NVim appear as
    (property) timeout: NonNullable<number | boolean | undefined>
    instead of
    (property) timeout: number | boolean

Answer №1

If you want to ensure all optional props are required in TypeScript, you can achieve this by using the -? notation.


type Props = {
    title: string
    color?: string
    timeout?: number | boolean
}
type OptionalProps<T extends object> =  {
    [K in keyof T as T extends Record<K, T[K]> ? never : K]-?: T[K]
}


type RequiredProps = OptionalProps<Props>

Check out the code on Playground

Answer №2

To create a mapped type similar to this:

type RequiredOptional<T> = {
  [K in keyof T as T extends Record<K, T[K]> ? never : K]-?: T[K];
};

You could also do it like this:

type RequiredOptional<T> = Required<{
  [K in keyof T as T extends Record<K, T[K]> ? never : K]: T[K];
}>;

And when you want to implement it:

type RProps = RequiredOptional<Props>;

You were on the right track towards the solution. What was missing:

  1. Utilize the Required utility or remove optional attributes using '-?'
  2. Embed the 'never' key directly instead of first identifying optional keys and then modifying them

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

Angular 2 module that is loaded lazily - service does not follow singleton pattern

After successfully implementing lazy loading modules into my application, I have ensured that the app.module.ts is properly configured. @NgModule({ declarations: [ AppComponent, HeaderComponent, HomeComponent ], imports: [ BrowserMod ...

Avoid invoking a TypeScript class like a regular function - _classCallCheck prevention

I am currently developing a TypeScript library that needs to be compatible with all versions of JavaScript. I have noticed that when calling a class in TS without using new, it does not compile properly, which is expected. In ES6/Babel, a class automatica ...

Why does my useEffect consistently execute after the initial rendering, despite having specified dependencies?

const [flag, setFlag] = React.useState(false) const [username, setUsername] = React.useState('') const [password, setPassword] = React.useState('') const [errorUsername, setErrorUsername] = React.useState(true) const [er ...

Converting JSON into Typescript class within an Angular application

As I work on my app using angular and typescript, everything is coming together smoothly except for one persistent issue. I have entity/model classes that I want to pass around in the app, with data sourced from JSON through $resource calls. Here's ...

Issue Arising from Printing a Custom Instruction in a Schema Generated Document

When dynamically adding a directive, the directive is correctly generated in the output schema. However, it seems to be missing when applied to specific fields. Here is how the directive was created: const limitDirective = new graphql.GraphQLDirective({ na ...

"Troubleshooting the issue of Angular's ng-selected not functioning properly within an edit

https://i.stack.imgur.com/ZpCmx.png https://i.stack.imgur.com/h3TA6.png TS Pincodes: Array<string> = []; Html <ng-select [items]="Pincodes" [searchable]="true" [multiple]="true" [(ngModel)]="updateZoneDetails ...

Tips for specifying the return type of app.mount()

Can I specify the return value type of app.mount()? I have a component and I want to create Multiple application instances. However, when I try to use the return value of mount() to update variables associated with the component, TypeScript shows an error ...

When attempting to add a variable using the next() function, I encountered an error with the BehaviorSubject. The error message displayed was "this.count.next is not a function"

In my Angular service, there is a variable called count that I need to monitor for updates. Whenever this count variable is updated, I want to assign its new value to another variable in a separate component. import {BehaviorSubject} from "rxjs/BehaviorSu ...

When utilizing the Map.get() method in typescript, it may return undefined, which I am effectively managing in my code

I'm attempting to create a mapping of repeated letters using a hashmap and then find the first non-repeated character in a string. Below is the function I've developed for this task: export const firstNonRepeatedFinder = (aString: string): strin ...

Utilizing Typescript for directive implementation with isolated scope function bindings

I am currently developing a web application using AngularJS and TypeScript for the first time. The challenge I am facing involves a directive that is supposed to trigger a function passed through its isolate scope. In my application, I have a controller r ...

When employing GraphQL Apollo refetch with React, the update will extend to various other components as well

My current setup involves using react along with Apollo. I have implemented refetch in the ProgressBar component, which updates every 3 seconds. Interestingly, another component named MemoBox also utilizes refetch to update the screen at the same int ...

The fillFormValues function is not functioning properly within the mat-select element

I need help filling a form value by id. This function successfully retrieves the value: fillFormValues(expenseCategory: ExpenseCategory): void { console.log('response', expenseCategory.parent_category) this.aa= expenseCategory.parent_c ...

Using TypeScript: Union Types for Enum Key Values

Here's the code in the TS playground too, click here. Get the Enum key values as union types (for function parameter) I have managed to achieve this with the animals object by using key in to extract the key as the enum ANIMALS value. However, I am s ...

Guide on linking enum values with types in TypeScript

My enum type is structured as follows: export enum API_TYPE { INDEX = "index_api", CREATE = "create_api", SHOW = "show_api", UPDATE = "update_api", DELETE = "destroy_api" }; Presently, I have a f ...

Leverage Angular2 validators beyond FormControl's limitations

As I work on developing a model-driven form in Angular2 RC5, one of the features I am implementing is the ability for users to add multiple entries either manually or by importing from a file. To display the imported data in a table, I utilize JavaScript t ...

Pass an array of objects to an Angular 8 component for rendering

Recently, I started working with Angular 8 and faced an issue while trying to pass an array of objects to my component for displaying it in the UI. parent-component.ts import { Component, OnInit } from '@angular/core'; @Component({ selector: ...

Can you explain the distinction between `any[]` and `{ [s: string]: any }`?

I was attempting to make this code snippet function properly: test(a: any[]) { let b: string[][] = []; b.push(Object.keys(a[0])); b.push(...a.map(e => Object.values(e))); } However, the compiler is throwing an error for the b.push(...a.ma ...

shortcut taken in inferring now exported

When using a default export, if the expression consists only of a variable identifier, the type inferencer defaults to the declaration of the variable instead of the actual type of the expression. Is this behavior intentional or is it a bug? // b.ts const ...

Issues with implementing Dark mode in TailwindCSS with Nuxt.js

After spending a couple of days on this, I'm still struggling to get the dark mode working with Tailwind CSS in Nuxt.js. It seems like there might be an issue with the CSS setup rather than the TypeScript side, especially since I have a toggle that sw ...

Difficulty fetching data on the frontend with Typescript, React, Vite, and Express

I'm currently working on an app utilizing Express in the backend and React in the frontend with typescript. This is also my first time using Vite to build the frontend. While my APIs are functioning correctly, I am facing difficulties fetching data on ...