What is the equivalent for \vfill between list items?

In Latex, I can do

Some problem
\begin{enumerate}
    \item part (a) \vfill
    \item part (b) \vfill
    \item part (c) \vfill
\end{enumerate}

in order to give enough spaces in one page.

What is the counterpart in typst? I tried the following.

Some problem
+ part (a) #v(1fr)
+ part (b) #v(1fr)
+ part (c) #v(1fr)

which results in 3 pages.

Hello. If that’s all you need, you can do

Some problem
#[
  #show enum.item: it => it + v(1fr)
  + part (a)
  + part (b)
  + part (c)
]

As par.leading can’t take fraction values:

#show enum: set par(leading: 5em)

Thank you. But this does not solve it. This makes the numbering be 1, 1, 1 instead of 1, 2, 3

You could combine @Andrew 's solution with a custom counter:

Some problem
#[
  #let enumcounter = counter("enumcounter")
  #enumcounter.update(1)
  #show enum.item: it => context {
    if it.number != none {
      return it
    }
    enumcounter.step()
    enum.item(
      enumcounter.get().first(),
      it.body
    ) + v(1fr)
  }
  + part (a)
  + part (b)
  + part (c)
]

Yep, but this is overcomplicated a bit. Here you go:

Some problem
#[
  #show enum.item: it => {
    let enum-counter = counter("enum-counter")
    if it.number != none { return it }
    enum-counter.step()
    context enum.item(..enum-counter.get(), it.body)
    v(1fr)
  }
  + part (a)
  + part (b)
  + part (c)
]

I actually was thinking at first with the classic processed label hack, but using a built-in field would generally be better, unless it’s actually be used. Then it will break.

#show enum.item: it => {
  if it.has("label") and it.label == <processed> { return it }
  [#enum.item(...)<processed>]
}

#let vfill-enum(doc) = {
  let enum-counter = counter("enum-counter")
  enum-counter.update(0)
  show enum.item: it => {
    if it.number != none { return it }
    enum-counter.step()
    context enum.item(..enum-counter.get(), it.body)
    v(1fr)
  }
  doc
}

Some problem
#[
  #show: vfill-enum
  + part (a)
  + part (b)
  + part (c)
]

Related: Resumable enum numbering · Issue #325 · typst/typst · GitHub

Then, it will be a bit hard to modify it if I want to give more space to one problem, e.g., #v(2fr). Finally, I made a #question.

#let question_counter = counter("question")

#let question(body, points: none) = {
  question_counter.step(level: 1)
  let number = context question_counter.display("1.")
  number
  if points != none [
    (#points pt)
  ]
  body
  linebreak()
}

#question(points: 3)[
  #lorem(30)
  
  #v(1fr)
]

#question[
  #lorem(20) #v(2fr)
]

#question[
  #lorem(40) #v(1fr)
]

Is it a better idea that typst should not stretch an enum.item to the whole page? Maybe I shall open an issue on Github?

Yeah, because there was no mention of 2fr and you can’t even add numbers to \vfill. Which is why I said, “If that’s all you need”. The better the question, the better the answer.

It seems you’re building an exam or a questionnaire, maybe the package tutor – Typst Universe might be of help. I’ve never used it, but I know the person personally who created it.

That one looks nice. The thing is that I am promoting Typst to others. If they ask me how to do a similar thing as the \item,\vfill in Latex, I can only tell them to manually setup a counter or use some package. They will certainly feel disappointed because for a familiar behavior, they have to find some way to crack the nuts. This is why I wonder whether it is a better idea to change the behavior of enum.item.

I’ve never seen this used. If this is a common thing, then it’s better to open a feature request.