Typescript: Type that requires at least one property

Viewed 4807

Consider that I have the following type:

type SomeType = {
  propOne: any;
  propTwo: any;
  propThree: any;
}

The propOne is required, propTwo and propThree are optional but at least one of them is required. How can I define the type with that constraint?

// The following code is my expectation
let someVar1: SomeType = { propOne: 1, propTwo: "two" } //Okay
let someVar2: SomeType = { propOne: 1, propThree: "three" } //Okay
let someVar3: SomeType = { propOne: 1, propTwo: "two", propThree: "three" } //Okay
let someVar4: SomeType = { propOne: 1 } //Not Okay
2 Answers

You can use the same trick even after your edit:

type SomeType = {
  propOne: number;
  propTwo?: string;
  propThree?: string;
} & ({
  propTwo: string;
} | {
  propThree: string;
})

let someVar1: SomeType = { propOne: 1, propTwo: "two" } //Okay
let someVar2: SomeType = { propOne: 1, propThree: "three" } //Okay
let someVar3: SomeType = { propOne: 1, propTwo: "two", propThree: "three" } //Okay
let someVar4: SomeType = { propOne: 1 } //Not Okay

function f(s: SomeType) {
  let p1 = s.propOne; // number
  let p2 = s.propTwo; // string | undefined
  let p3 = s.propThree; // string | undefined
}

It forces you to have at least one property at declaration time, and it allows you to use both properties of the type when using objects of that type.

Playground

Here is type that is union type of 2 objects:

type SomeType = {
    propOne: any;
} | {
  propTwo: any;
}

Typescript will require object's type to be compatible to one of type in this union. Here is solution in playground

Note: This is the simplest solution if you really have only two properties.

Related