If your type is simple, one option is to define all the valid cases. If it's a complex type, this might not be maintainable.
type MyType = { foo: string } | { bar: string } | { foo: string; bar: string; }
function someFunction(obj: MyType) {}
someFunction({ foo: "baz" }); // valid
someFunction({ bar: "baz" }); // valid
someFunction({ foo: "baz", bar: "baz" }); // valid
someFunction({}); // error
TypeScript playground
Another solution is shared in this answer: https://stackoverflow.com/a/49725198/2690790
type RequireAtLeastOne<T, Keys extends keyof T = keyof T> = Pick<
T,
Exclude<keyof T, Keys>
> &
{
[K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>>
}[Keys];
interface MyType {
foo: string;
bar: string;
}
function someFunction(obj: RequireAtLeastOne<MyType>) {}
someFunction({ foo: "baz" }); // valid
someFunction({ bar: "baz" }); // valid
someFunction({ foo: "baz", bar: "baz" }); // valid
someFunction({}); // error
TypeScript playground