Reputation: 5772
Consider the following (non-compiling) TypeScript example:
type Optional<T> = { [K in keyof T]?: T[K] };
interface Foo {
name: string;
age: number;
}
function foo<A extends Optional<Foo>, B extends Optional<Foo>, A & B extends Foo>(a: A, b: B) : Foo {
return {...a, ...b};
}
The idea of foo
is to take two partial instances of Foo
and enforce that their intersection (at least) extends Foo
.
Is there a possible way to construct such a constraint?
If that was possible, is it possible to extend the solution to a flexible amount of argument? I.e. foo
not only taking 2 arguments, but n
arguments.
function foo<A extends Optional<Foo>[]>(a: ...A) : Foo {
...
}
Upvotes: 1
Views: 54
Reputation: 250016
You can create a tuple type for a rest parameter that requires all that all properties of the last element in the tuple contains any properties that haven't already been specified:
interface Foo {
name: string;
lastName: string;
age: number;
id: number
}
function foo<A extends Partial<Foo>= {}, B extends Omit<Foo, keyof A> = Omit<Foo, keyof A>>(...a: [...A[], B]) : Foo {
return Object.assign({}, ...a) as Foo;
}
let x = foo({ name: "" }, { lastName: "" }, { id: 0, age: 1})
let x2 = foo({ name: "" }) // error
let x4 = foo({ name: "" }, { lastName: "" }, { id: 0 }) // error
let x3 = foo() // error
Although the errors might be a bit hard to read
Upvotes: 2