1

How can I write a function that checks that SOME fields on a type are required?

The IFinancingModel also has statusDetails which might be undefined on a valid financing so using Required<> is not correct.

export function validFinancing(
    financing: IFinancingModel | undefined,
): financing is Required<IFinancingModel> {
    return !!(
        projectFinancing && 
        projectFinancing.applicationId && 
        projectFinancing.state
    );
}
user1283776
  • 19,640
  • 49
  • 136
  • 276

1 Answers1

3

You can use Pick to select some properties of the type and make them required and make intersect that with the original to produce the desired type:

type RequireSome<T, K extends keyof T> = Required<Pick<T, K>> & T;
interface IFinancingModel {
  applicationId?: number;
  state?: string;
  statusDetails?: string
}

export function validFinancing(
    financing: IFinancingModel | undefined,
): financing is RequireSome<IFinancingModel, 'applicationId' | 'state'> {
    return !!(
        financing && 
        financing.applicationId && 
        financing.state
    );
}
declare let o: IFinancingModel | undefined;
if (validFinancing(o)) {
  o.applicationId.toExponential // number 
  o.state.anchor; // string
  o.statusDetails.big // err can be undefined
}
Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357
  • Just curious, how could you make `RequiredSome` also remove `null` from properties? `Required<>` seems to only remove `undefined`... – Aaron Beall Mar 28 '19 at 15:50
  • @Aaron That can be done but not with `Required` we will need a more complicated type with a conditional. Let me give it a try and I'll post it – Titian Cernicova-Dragomir Mar 28 '19 at 15:52
  • I came up with `{ [P in K]-?: NonNullable } & Pick>` but seems over-complicated... (sorry to hijack answer) – Aaron Beall Mar 28 '19 at 15:52
  • 1
    @Aaron this is what I have :`type RequiredAndNotNull= { [P in keyof T]-?:Exclude } type RequireSome = RequiredAndNotNull> & T;` if a property is `string | null | undefined` and you intersect it with `string` it will become `string` no need to do any extra picking – Titian Cernicova-Dragomir Mar 28 '19 at 15:54