```ts
/**
 * Replays a stream of integer cache keys against a direct-mapped cache with a given number of slots,
 * counting hits and evicting on every miss.
 *
 * @param keys - Array of integers representing cache keys to replay.
 * @param slots - Positive integer representing the number of slots in the cache.
 * @returns The total number of hits.
 */
export function slotHits(keys: number[], slots: number): number {
  if (!Array.isArray(keys)) {
    throw new Error('keys must be an array');
  }
  if (!Number.isInteger(slots) || slots <= 0) {
    throw new Error('slots must be a positive integer');
  }

  const cache = new Array(slots).fill(null);
  let hits = 0;

  for (const key of keys) {
    if (!Number.isInteger(key)) {
      throw new Error('all keys must be integers');
    }
    const slotIndex = Math.abs(key % slots);
    if (cache[slotIndex] === key) {
      hits++;
    } else {
      cache[slotIndex] = key;
    }
  }

  return hits;
}
```