To ensure that intervals
are able to be assigned to Array<Intervals>
, a simple check can be implemented:
const intervalsMisspelled: Array<Intervals> =
['weekly', 'biweekly', 'annually', 'monthly', 'totul']; // error, "totul"
However, this does not account for missing elements:
const intervalsMissing: Array<Intervals> =
['weekly', 'biweekly', 'annually', 'monthly']; // oops, no error but missing "total"
To address this issue, you can create a utility function called ensureArray()
. This function takes a type parameter T
(in this case, Intervals
) and returns another function which accepts parameters of type T
and infers an array type A
based on those parameters. If any element in the A
array (A[number]
) is narrower than type T
, an error will be triggered indicating that something has been left out. Here's how you can implement this solution:
const ensureArray = <T>() => <A extends T[]>(
...a: A & ([T] extends [A[number]] ? A : never)
): A => a;
const ensureIntervalsArray = ensureArray<Intervals>();
const intervals = ensureIntervalsArray(
'annually', 'biweekly', 'monthly', 'total', 'weekly'); // okay
const intervalsMisspelled = ensureIntervalsArray(
'annually', 'biweekly', 'monthly', 'totul', 'weekly'); // error, "totul"
const intervalsMissing = ensureIntervalsArray(
'annually', 'biweekly', 'monthly', 'weekly'); // error,
// [string, string, string, string] is not assignable to never
This implementation works, although the error message generated for intervalsMissing
might be unclear at first glance. Unfortunately, due to current limitations in TypeScript, custom type errors cannot be easily created.
An alternative approach provides a more descriptive but convoluted error message:
const ensureArray = <T>() => <A extends T[]>(
...a: A & ([T] extends [A[number]] ? A :
{ errorMessage: [Error, "You are missing", Exclude<T, A[number]>] })
): A => a;
const ensureIntervalsArray = ensureArray<Intervals>();
const intervalsMissing = ensureIntervalsArray(
'annually', 'biweekly', 'monthly', 'weekly'); // error,
// Property 'errorMessage' is missing in type
// '["annually", "biweekly", "monthly", "weekly"]'
// but required in type '{ errorMessage: [Error, "You are missing", "total"]; }'
Hopefully one of these approaches meets your requirements. Best of luck!