Develop a new data structure using the parameter type as a foundation

I am grappling with a generic function that returns another function.

While typing it, there might be required keys. These required keys are optional for the initial function, but become mandatory for the subsequent function if they were not provided initially. However, if they are provided in the first function, they then become optional for the second function (for overwriting purposes).

Here is what I have attempted so far, but unfortunately, I have not been able to solve it yet.

function myFunc<T>(opts?: Partial<T>) {
  // this typing is incorrect, and I am struggling to fix it
  return (moreOpts: Omit<T, keyof typeof opts> & Partial<T>) => {
    // perform some actions
  }
}

type TestType = {
  name: string;
  age: number;
}

const test1 = myFunc<TestType>({ name: 'John Doe' }) // no error
test1() // error -- age is required

const test2 = myFunc<TestType>() // no error
test2({ name: 'John Doe', age: 23 }) // no error

const test3 = myFunc<TestType>({ name: 'John Doe', age: 23 }); // no error
test3({ name: 'Jane Doe' }) // no error

const test4 = myFunc<TestType>({ name: 'John Doe' }); // no error
test4({ name: 'Jane Doe' }) // error -- age is required

const test5 = myFunc<TestType>({ name: 'John Doe', age: 23 }); // no error
test5() // no error

Answer №1

If I grasp the essence of your inquiry correctly, you can achieve it by utilizing 3 function calls (the first one being where you specify the initial generic type to establish the base type for validation in the subsequent ones).

Feel free to click on the following playground link to explore and experiment with the code, verify if it aligns with your requirements, and access compiler error messages as well as other IntelliSense functionalities:

TS Playground

function createValidator<T>() {
  return <First extends Partial<T>>(opts?: First) => {
    return (...params: Exclude<keyof First, keyof T> extends never ?
      [opts?: Omit<T, keyof First> & Partial<Pick<T, Extract<keyof First, keyof T>>>]
      : [opts: Omit<T, keyof First> & Partial<Pick<T, Extract<keyof First, keyof T>>>]) => {};
  };
}

type TestType = {
  name: string;
  age: number;
};

const outer1 = createValidator<TestType>();
const inner1 = outer1({ name: 'John Doe', size: 'green' }); // no error
inner1(); // error -- needs age

const outer2 = createValidator<TestType>();
const inner2 = outer2(); // no error
inner2({ name: 'John Doe', age: 23 }); // no error

const outer3 = createValidator<TestType>();
const inner3 = outer3({ name: 'John Doe', age: 23 }); // no error
inner3({ name: 'Jane Doe' }); // no error

const outer4 = createValidator<TestType>();
const inner4 = outer4({ name: 'John Doe' }); // no error
inner4({ name: 'Jane Doe' }); // error -- needs age

const outer5 = createValidator<TestType>();
const inner5 = outer5({ name: 'John Doe', age: 23 }); // no error
inner5(); // no error

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

Vue-i18n does not offer a default export option

Hello everyone! This is my first experience using vue-i18n in a project with TypeScript + Vue. Following the instructions from the official site, I installed it using yarn install vue-i18n. Next, I tried to import it into main.ts using import VueI18n from ...

Create a Typescript index signature that incorporates individual generic types for each field

Many times, the keys of a record determine its value. For instance: const record = { [2]: 5, ["string"]: "otherString", ["there is"]: "a pattern" } In these instances, each key of type K corresponds to the ...

When trying to compile FirebaseUI with typescript and react-redux, users may encounter issues

I'm attempting to implement firebaseui for a login feature in react-redux using typescript. Here is the code snippet: import firebase from 'firebase'; import firebaseui from 'firebaseui'; import fire from '../FirebaseCreds&ap ...

Oops! There seems to be an issue with locating a differ that supports the object '[object Object]' of type 'object', like an Array

I'm currently encountering an error that reads: (ERROR Error: NG02200: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables, such as Arrays. Did you mean to use the key ...

Discovering ways to fetch an array of objects using object and arrays in JavaScript

When comparing an array of objects with a single object and listing the arrays in JavaScript, specific conditions need to be met to retrieve the array of objects: If the itemvalue and idvalue are the same, check if the arrobj cid has the same codevalue ...

Exploring the Power of Observables in Angular 2: Leveraging the Versatility of

As a student working on developing a simple WebApp and Server, I have encountered some issues with Http.post and Http.get methods using Observables. My main challenge is related to posting a boolean value to the server when a button is pressed. While the ...

How to access parent slider variables in an Angular component

I've developed a slider as the parent component with multiple child components. See the demo here: https://stackblitz.com/edit/angular-ivy-gcgxgh?file=src/app/slide2/slide2.component.html Slider in the parent component: <ng-container *ngFor=&quo ...

Convert an interface type variable to a string representation

I'm just starting to learn angular and I'm attempting to convert my response from an interface type into a string so that I can store it in session storage. However, when I try to save them, they are being stored as [object] in the session storag ...

Do [(ngModel)] bindings strictly adhere to being strings?

Imagine a scenario where you have a radiobutton HTML element within an angular application, <div class="radio"> <label> <input type="radio" name="approvedeny" value="true" [(ngModel)]=_approvedOrDenied> Approve < ...

Angular 4: Utilizing reactive forms for dynamic addition and removal of elements in a string array

I am looking for a way to modify a reactive form so that it can add and delete fields to a string array dynamically. Currently, I am using a FormArray but it adds the new items as objects rather than just simple strings in the array. Here is an example of ...

Automatic generation of generic types in higher-order functions in TypeScript

function createGenerator<P extends object>(initialize: (params: P) => void) { return function (params: P): P { initialize(params) return params } } const gen = createGenerator(function exampleFunction<T>(param: T) { console.lo ...

Setting up a Form submit button in Angular/TypeScript that waits for a service call to finish before submission

I have been working on setting up a form submission process where a field within the form is connected to its own service in the application. My goal is to have the submit button trigger the service call for that specific field, wait for it to complete suc ...

Dealing with type errors involving null values when using interfaces in Typescript

I encountered an issue related to the error property within the defaultState constant: interface AuthState<T = any> { auth: T; error: null | Error; loading: boolean; } export const defaultState: { auth: null | AuthState } = { auth: null, e ...

Dealing with TSLint errors within the node_modules directory in Angular 2

After installing the angular2-material-datepicker via NPM, it is now in my project's node_modules folder. However, I am encountering tslint errors that should not be happening. ERROR in ./~/angular2-material-datepicker/index.ts [1, 15]: ' should ...

A glitch was encountered during the execution of the ionic-app-scripts subprocess

I recently started using Ionic 3 and created an application that I'm trying to convert into an APK. To generate a debug (or testing) android-debug.apk file, I used the following CLI command: ionic cordova build android --prod The pages are declared ...

In the Vercel production environment, when building Next.js getStaticPaths with URL parameters, the slashes are represented as %

I've encountered an issue while implementing a nextjs dynamic route for my static documentation page. Everything works perfectly in my local environment, and the code compiles successfully. However, when I try to access the production URL, it doesn&ap ...

Navigating between different views and pages within Angular FullCalendar can be achieved by utilizing the appropriate handlers for next,

After successfully integrating Angular fullCalendar into my Angular project and displaying events that I can click on, I found myself stuck when trying to handle clicks on the next and prev buttons as well as view changes. Unfortunately, the official docum ...

Establish a function within an interface using the name obtained from a constant in Typescript

How can I define functions within an interface using constants as function names? I have a const array containing event names and I want to create an ServerToClientEvents interface for SocketIO. I can define a function like this and it will work: interfac ...

Add an asterisk before each line of comment when working in a TypeScript file using the VS Code IDE

Within my VS Code workspace, I am using the Typescript language and would like to format my comments across multiple lines with a specific style (look out for the star character) /** *@desc any text * any text */ However, when I attempt to write a comm ...

What is the best way to utilize ngFor for iterating through a Map variable of classes in TypeScript?

In my TypeScript file, I have a class named `myMap` that contains a variable called `navList`, which is of type Map<string, string> and holds multiple key-value pairs. I am currently attempting to iterate over the values stored in `navList` within my ...