TypeScript: The Incomplete "Partial" Type

Environment

The current version of TypeScript is 3.2.1 and the configuration file "tsconfig.json" looks like this:

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "esModuleInterop": true
  }
}

Question

I am interested in finding a type similar to "Partial" in TypeScript.

type Entity = {
  a: string,
  b: string,
  c?: string,
};

type Ham = MyType<Entity, 'b'>;
/**
 * expected to equal
 * {
 *   a: string,
 *   b?: string, // changed to be optional
 *   c?: string,
 * };
 */

P.S. Titian and t7yang

Thank you both for your input. I have tested both types and they pass the compiler's check successfully!

const abc = { a: 'a', b: 'b', c: 'c' };
const ab = { a: 'a', b: 'b' };
const ac = { a: 'a', c: 'c' };
const a = { a: 'a' };

// by t7yang
let test1Abc: OptionalKey<Entity, 'b'> = abc;
let test1Ab: OptionalKey<Entity, 'b'> = ab;
let test1Ac: OptionalKey<Entity, 'b'> = ac;
let test1A: OptionalKey<Entity, 'b'> = a;

// by Titian Cernicova-Dragomir    
let test2Abc: PickPartial<Entity, 'b'> = abc;
let test2Ab: PickPartial<Entity, 'b'> = ab;
let test2Ac: PickPartial<Entity, 'b'> = ac;
let test2A: PickPartial<Entity, 'b'> = a;

Answer №1

To selectively choose which properties to make optional in an object, you can combine the Pick and Partial utilities while using Exclude to exclude certain keys:

type Entity = {
   a: string,
   b: string,
   c?: string,
};

type PickPartial<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>> & Partial<Pick<T, K>>
type CustomType = PickPartial<Entity, 'b'>; // a, b? , c?

Answer №2

A straightforward solution:

type PickPartial<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
type PartialExcept<T, K extends keyof T> = Pick<T, K> & Partial<Omit<T, K>>;

This approach was devised before Typescript 3.5 introduced the Omit helper.

It's worth noting that using string unions allows you to specify multiple attributes as optional:

type Full = {
  a: string;
  b: string;
  c: string;
}

// These definitions are identical
type ARequired = PickPartial<Full, 'b' | 'c'>;
type ARequired = PartialExcept<Full, 'a'>;

Answer №3

type Entity = {
  a: string,
  b: string,
  c?: string,
};

type OptionalKey<T, O extends keyof T> = Pick<T, Exclude<keyof T, O>> & Partial<{ [P in O]: T[P] }>;

const a: OptionalKey<Entity, 'b'> = {
  a: 'a',
}

const ab: OptionalKey<Entity, 'b'> = {
  a: 'a',
  b: 'b'
}

const ac: OptionalKey<Entity, 'b'> = {
  a: 'a',
  c: 'c'
}

The concept here involves selecting specific properties to be optional and then combining them with the desired type to create optional properties.

To see this in action, you can explore it further on the typescript playground

Answer №4

Here is a simplified version of the accepted answer using Intersection of a Partial and Pick without any extra types:

type Entity = {
  a: number,
  b: number,
  c?: number,
}

type Ham = Partial<Entity> & Pick<Entity, Exclude<keyof Entity, 'b'>>;

const b: Ham[] = [{ a: 1 }, { a: 1, b: 1 }, { a: 1, c: 1 }, { a: 1, b: 1, c: 1 }]; // OK.
const c: Ham = {}; // Bad.

Playground

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

When working with Angular 2 and Typescript, a common error message that may be encountered is "TypeError

Currently diving into Angular 2 and encountered a stumbling block while attempting to create a service. Despite my efforts in finding a solution, I seem to be missing something crucial. Error: A problem arises in angular2-polyfills.js:1243 with the error ...

The router.navigate() function seems to be malfunctioning as it is not working as

I have a method defined as follows: private redirect(path: string): void { this.router.navigate([path]); } This method is called within another method like so: private onError(error: any): void { switch (error.status) { case 401: / ...

Issue with hydration when logging in with Next-Auth in NextJS 13.4

Step-by-step Instructions: 'node -v' -> v18.16.1 'npx -v' -> 9.8.0 To start, I created a new Next.js app by running npx create-next-app@latest in the terminal within my app folder. Here is a link to the package.json file. Nex ...

What is the best way to send the body in a GET request using Angular 2+?

My API's GET method is located at "http://abc/abc" Typically, the GET method includes parameters as get(url, options), with only two arguments. However, in my scenario, I need to include a body with the request. The body structure is as follows: { ...

What steps can be taken to resolve the Angular error stating that the property 'bankCode' is not found on type 'User' while attempting to bind it to ng model?

I'm encountering an issue with my application involving fetching values from MongoDB and displaying them in an Angular table. I've created a user class with properties like name and password, but I keep getting errors saying that the property doe ...

Error in Angular: Unable to bind FormControl to input due to unexpected issue

I need help resolving a common error I'm encountering. I have forms in two different sections of my application, and while the form functions correctly in one section, it is not working in the other. Both ReactiveFormsModule and FormsModule are import ...

Troubleshooting font color issues with PrimeNG charts in Angular

I have a chart and I am looking to modify the color of the labels https://i.sstatic.net/vsw6x.png The gray labels on the chart need to be changed to white for better readability Here is my code snippet: HTML5: <div class="box-result"> ...

Examining React components with Enzyme for event usage in components

Struggling with testing react components that utilize event.target in events has been a challenge for me. Take for example the component code snippet below; import * as React from 'react'; import { generateGuid } from '../../../utilities/Gu ...

What is the functionality of input onChange in React when using state management?

Whenever I try to log the value of the input after each onChange event, there seems to be an odd one event delay. For example, if 'some text' is the default input value and I remove the letter 't' by pressing backspace/delete, it first ...

The limitations of Typescript types influence the program's behavior

As a newcomer to the Typescript environment, I am currently developing a test application to familiarize myself with it. However, I have encountered an issue regarding type restrictions that seems to be not working as expected. In my class, I have defined ...

Having trouble connecting useRef eventListeners in TypeScript/JavaScript

Trying to connect an eventListener to a container in Typescript using useRef and useEffect hooks. The issue we are encountering is: No overload matches this call. Overload 1 of 2, '(type: keyof HTMLElementEventMap, listener: (this: HTMLDivElement, ev: ...

Encasing a drop-down menu within a personalized container

I am looking to create a custom HTML element that mimics the behavior of the native <select> element but also triggers a specific update function whenever an attribute or child node is modified. This is essential for incorporating the bootstrap-selec ...

Utilizing TypeScript with Msal-React for Prop Type Validation

I'm currently implementing authentication in my app using msal-React. Within my app, I have a component that utilizes msalcontext and is wrapped by withMsal: function App(props: any) { return ( <> <AuthenticatedTemplate> ...

Webpack and TypeScript are unable to locate the declaration file for Vue

In my current project, I have integrated Vue for frontend development while still maintaining a significant amount of legacy code in TypeScript and jQuery. The legacy code resides within a 'ts' folder, whereas the new Vue single file components a ...

Unable to assign to 'disabled' as it is not recognized as a valid attribute for 'app-button'

How to link the disabled property with my button component? I attempted to add 'disabled' to the HTML file where it should be recognized as an input in the button component (similar to how color and font color are recognized as inputs) ... but ...

Having issues with importing momentjs by reference in TypeScript with amd configuration

I'm puzzled by the difference in behavior between these two snippets: import * as moment from "../Typings/moment"; One works, while this one doesn't: /// <reference path="../Typings/moment.d.ts" /> import * as moment from "moment"; It t ...

Is it possible to import node_modules from a specific directory mentioned in the "main" section of the package.json file?

Is it feasible to import from a source other than what is defined by the "main" setting? In my node_modules-installed library, the main file is located at lib/index.js With es2015 imports (source generated from ts compiled js), I can use the following ...

Tips for transforming TypeScript Enum properties into their corresponding values and vice versa

Situation Imagine having an enum with string values like this: enum Fruit { Apple = "apple", Orange = "orange", Banana = "banana", Pear = "pear" } Users always input a specific string value ("apple", "banana", "orange", "pear") from a drop-down li ...

Locate and retrieve the item that appears most often in a given array

In order to determine the mode of an array consisting of integer numbers only, I must create a function named findMode. If the array is empty, the function should return 0. Otherwise, it should return the element that occurs most frequently in the array. I ...

Setting options using the form group in dropdowns in Angular can greatly enhance the user experience

I have created a FormGroup called holidayform and set it up as follows: holidayform: FormGroup; this.holidayform = this.fb.group({ title: ['', [Validators.required]], entryDate: ['',], }) this.holidayform.patchValue ...