```ts
export function bestHarvest(yields: number[]): number {
  if (!Array.isArray(yields)) {
    throw new Error("Input must be a list");
  }
  for (const y of yields) {
    if (typeof y !== "number" || !Number.isInteger(y) || y < 0) {
      throw new Error("Each yield must be a non-negative integer");
    }
  }
  const n = yields.length;
  if (n === 0) return 0;

  const dp: number[] = new Array(n).fill(0);
  dp[0] = yields[0];
  for (let i = 1; i < n; i++) {
    dp[i] = Math.max(dp[i - 1], dp[i - 2] + yields[i]);
  }
  return dp[n - 1];
}
```

**Verification against edge cases:**

| Input | Expected | Reasoning |
|-------|----------|-----------|
| `[]` | 0 | Empty list → 0 |
| `[5]` | 5 | Single day, take it |
| `[5, 1, 1, 5]` | 10 | Take day 0 and day 3 (not consecutive) |
| `[1, 2, 3, 4, 5]` | 9 | Take 1, 3, 5 |
| `[0, 0, 0]` | 0 | All zeros |
| `[10, 10, 10]` | 20 | Take 0 and 2 |
| `[5, 1, 1, 5, 1, 1, 5]` | 15 | Take 0, 3, 6 |
| `[100]` | 100 | Single large value |
| `[1, 2]` | 3 | Take both (not consecutive) |
| `[1, 2, 3]` | 4 | Take 1 and 3 |

**DP correctness:** `dp[i] = max(dp[i-1], dp[i-2] + yields[i])` — either skip day `i` (carry forward best up to `i-1`) or take day `i` (add to best up to `i-2`, since `i-1` must be off). Base cases: `dp[0] = yields[0]`, `dp[1] = max(yields[0], yields[1])`. This is the classic "house robber" DP with O(n) time and O(n) space.