How can I ensure an object includes some specific fields using Partial<>?
Asked Answered
C

2

7

I have a function with the following parameter:

const handleAccount = (
  account: Partial<IAccountDocument>,
  ...
) => { ... }

In no way can I change the interface for IAccountDocument to not require certain fields, i.e. I must use Partial<>. How can I make it so that IAccountDocument has specific fields included whilst also being allowed to be partially created?

Cavan answered 19/4, 2022 at 13:54 Comment(3)
typescriptlang.org/docs/handbook/utility-types.html - either pick or omit the appropriate fieldsSubtorrid
What does it mean for IAccountDocument to have specific fields included while also being Partial<IAccountDocument>?Elbertelberta
There is a field called _id, for example. If I don't set the parameter as Partial<>, it complains that it requires a document with the _id field; but if I do set the parameter to Partial<>, it allows documents without _id, which cannot happen.Cavan
S
8

Use the Pick utility type to choose some mandatory properties and combine it with Partial<IAccountDocument>.

// Let's say that a and b must be mandatory properties
interface IAccountDocument {
  a: number 
  b: number
  c: number
  d: number
  e: number
}

const handleAccount = (
  account: Pick<IAccountDocument, "a" | "b"> & Partial<IAccountDocument>
) => {}


// valid
handleAccount({a: 123, b: 123, c: 123})

// not valid
handleAccount({c: 23})
Sarraute answered 19/4, 2022 at 14:0 Comment(6)
But does this ensure that both a and b are required? As in my case, I'd need this.Cavan
yes, you get an error if you do not include a and bSarraute
Ah, I thought Pick worked as an or. Thanks, Tobias.Cavan
It actually doesn't work, at least in my case. With my partially-created object (Partial<IAccountDocument>), when I pass it into the handleAccount() I get Property 'practice' is optional in type 'Partial<IPatientDocument>' but required in type 'Pick<IAccountDocument, "migrationData" | "practice" | "accessGroups">'.ts(2345). I have the & Partial<IAccountDocument>, too (even though I am not 100% on what this bit actually does).Cavan
If you have an object with the type Partial<IAccountDocument> and pass it to the function, the information about which properties the object actually has is lost. You cannot pass objects of Partial<IAccountDocument> to the function as typescript has no way of knowing if all constraints are satisifiedSarraute
Hm, indeed. What it is I am trying to do then, I'm not sure it can be quite done. At least I learnt that. Thanks for your helpCavan
A
3

Typescript supports intersection types.

Borrowing from the answer by tobias-s:

// Let's say that a and b must be mandatory properties
type IAccountDocument {
  a: number 
  b: number
  c: number
  d: number
  e: number
}

type CustomPartialIAccountDocument = Partial<IAccountDocument> & {
  a: number 
  b: number
}

// valid
CustomPartialIAccountDocument ({a: 123, b: 123, c: 123})

// not valid
CustomPartialIAccountDocument ({c: 23})
Aleda answered 12/6, 2023 at 21:1 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.