Narrow down literal unions based on previously used values
It can be done just by using Question; however, it will be a complex type that will cause a horrible time for the compiler since it grows at the speed of power of two, and if you have more options (more than 10), the compiler will reach its limits and won't compile.
Instead, I would suggest adjusting Question to accept the Option[] as a generic parameter and assign the type of the elements of that generic parameter to default:
type Question<T extends Option[]> = {
  message: string;
  options: T;
  default: T[number];
};

Lastly, we will need a generic function that would create a question for us:
const createQuestion = <T extends Option[]>(question: Question<T>) => question;

Usage:
const q1 = createQuestion({
  message: "first question",
  options: ["a", "b"],
  default: "a",
});

const q2 = createQuestion({
  message: "second question",
  options: ["c", "d"],
  default: "a", // Expected error
});

playground

The scenario is the following:
type Option = 'a' | 'b' | 'c' | 'd'

type Question = {
  message: string;
  options: Option[];
  default: Option // here's the issue
}

I want the default prop to be the one of the options used inside question.options. For example:
const q1: Question = {
  message: 'first question',
  options: ['a', 'b'],
  default: 'a'
}

const q2: Question = {
  message: 'second question',
  options: ['c', 'd'],
  default: 'a' // I want this to give an error because 'a' is not in 'c' | 'd'
}

How can I achieve this?
