E.g. I have a function to accept an array of configs. Each array element can be a subset of the config.
I’m currently doing it this way:
type Config = {
a: number,
b: number,
c?: number,
};
function fn(arr: Partial<Config>[]) {}
fn([{ a: 1, b: 1, c: 1 }]); // ok
fn([{ a: 1 }, { b: 1 }]); // ok
fn([{ a: 1 }]); // invalid config, but no TS error
The last function call is missing the required c
property. I want to check the whole array against the Config
type. I figured out this hack that seems to work:
// From https://stackoverflow.com/a/50375286
type UnionToIntersection<U> =
(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never;
function fn<T extends Partial<Config>>(
arr: T[] & (UnionToIntersection<T> extends Config ? any : never),
) {}
fn([{ a: 1, b: 1, c: 1 }]); // ok
fn([{ a: 1 }, { b: 1 }]); // ok
fn([{ a: 1 }]); // Type 'number' is not assignable to type 'never'
Is there a non-hacky way to do this? Ideally, the error message would be clearer.