Is it safe to assume computed property invariant only after init?

In the following code:

struct Book {
   let pages: [Page] = []
   
  var lastReadPage: Page {
        pages.first { $0.hasBookMark } ! // this property fails if the initialiser is not done
   }
  init(pages: [Page])  {
        self.pages = pages
        pages[0].hasBookMark = true // Now computed property will not fail
  }
}

Is it safe/ a good practice to to create the invariant (the sure knowledge that) the computed property won't fail, but only once the init is done?

Yes, it's safe. You cannot access the struct member(s) until the struct is initialised, so in this case until your init is called as it's the only one.

In fact you could change the second line to

let pages: [Page]

Normally when you use let to declare an immutable value, you have to supply a value as it can't be changed later. But in a class/struct you cannot access the member until the class/struct has been initialised, so it lets you leave it blank until you set it up in the initialiser, which it also forces you to do – not doing so is a compile error. This is useful if, as in this case, you want to ensure setup is done in the initialiser.

4 Likes