```typescript
/**
 * Split an array into consecutive groups of at most size elements, preserving order; the final group is shorter when the length does not divide evenly. An empty array yields an empty array. The input array must not be mutated. Throw an Error unless size is a positive integer.
 * @param items Input array
 * @param size Max size for each chunk
 */
export function chunk<T>(items: readonly T[], size: number): T[][] {
  // Validate the parameters
  if (size < 1 || !Number.isInteger(size)) throw new Error('Size must be a positive integer');
  const result = [];
  for (let i = 0; i < items.length; i += size) {
    result.push(items.slice(i, i + size));
  }
  return result;
}
```