```ts
export function spreadNightDuty(crew: string[], weights: number[], away: string[][]): string[] {
  if (crew.length === 0) {
    throw new Error("Crew cannot be empty");
  }
  if (new Set(crew).size !== crew.length) {
    throw new Error("Crew contains duplicate names");
  }
  for (const name of crew) {
    if (typeof name !== "string" || name.trim() === "") {
      throw new Error("Crew must contain non-empty string names");
    }
    if (name === "?") {
      throw new Error("Crew cannot contain the mark ?");
    }
  }
  if (weights.length === 0) {
    throw new Error("Weights cannot be empty");
  }
  for (const weight of weights) {
    if (weight !== 1 && weight !== 2) {
      throw new Error("Weights must be either 1 or 2");
    }
  }
  if (away.length !== weights.length) {
    throw new Error("Away list must be the same length as weights");
  }
  for (let i = 0; i < away.length; i++) {
    if (!Array.isArray(away[i])) {
      throw new Error("Each entry in away must be a list");
    }
    for (const name of away[i]) {
      if (typeof name !== "string" || name.trim() === "") {
        throw new Error("Away names must be non-empty strings");
      }
      if (!crew.includes(name)) {
        throw new Error("Away names must be in the crew");
      }
    }
  }

  const stood = new Map<string, number>();
  for (const name of crew) {
    stood.set(name, 0);
  }
  const nights: string[] = [];
  let previous1 = "";
  let previous2 = "";

  for (let night = 0; night < weights.length; night++) {
    let chosen = "";
    let minLoad = Infinity;
    for (const name of crew) {
      if (away[night].includes(name) || name === previous1 || name === previous2) {
        continue;
      }
      const currentLoad = stood.get(name)! + weights[night];
      if (currentLoad < minLoad || (currentLoad === minLoad && name < chosen)) {
        chosen = name;
        minLoad = currentLoad;
      }
    }
    if (chosen === "") {
      nights.push("?");
    } else {
      stood.set(chosen, stood.get(chosen)! + weights[night]);
      nights.push(chosen);
      previous2 = previous1;
      previous1 = chosen;
    }
  }

  return nights;
}
```