 	///
 	/// - parameters:
 	///   - inner: The inner property to wrap.
-	///   - body: The closure to invoke for any proposed value to `self`.
-	public convenience init<M: ComposableMutablePropertyProtocol>(
-		_ inner: M,
-		_ body: @escaping (M.Value) -> Result<M.Value, TransactionError>
-	) where M.Value == Value {
-		self.init(inner, transform: { $0 }, body)
-	}
-
-	/// Create an `TransactionalProperty` that presents `inner` as an
-	/// `TransactionalProperty` of `U` values and the same error type, and invoke
-	/// `body` with the proposed value whenever the setter is invoked.
-	///
-	/// If `success` is returned by `body`, the associated value would be
-	/// persisted to `inner`. Otherwise, the failure would be emitted by the
-	/// `validations` signal.
-	///
-	/// - parameters:
-	///   - inner: The inner property to wrap.
 	///   - transform: The value transform for the presentation.
 	///   - body: The closure to invoke for any proposed value to `self`.
-	public convenience init<U>(
-		_ inner: TransactionalProperty<U, TransactionError>,
-		transform: @escaping (U) -> Value,
-		_ body: @escaping (Value) -> Result<U, TransactionError>
+	public convenience init<T: _TransactionalPropertyProtocol>(
+		_ inner: T,
+		transform: @escaping (T.Value) -> Value,
+		_ body: @escaping (Value) -> Result<T.Value, TransactionError>
+	) where T.TransactionError == NoError {
+		self.init(inner, transform: transform, validator: body, validationSetup: nil)
+	}
+
+	private init<T: _TransactionalPropertyProtocol>(
+		_ inner: T,
+		transform: @escaping (T.Value) -> Value,
+		validator: @escaping (Value) -> Result<T.Value, TransactionError>,
+		validationSetup: ((MutableProperty<Result<(), TransactionError>>) -> Void)?
 	) {
-		self.init(inner, transform: transform, errorTransform: { $0 }, body)
-	}
-
-	/// Create an `TransactionalProperty` that presents `inner` as an
-	/// `TransactionalProperty` of the same value type and `E` errors, and invoke
-	/// `body` with the proposed value whenever the setter is invoked.
-	///
-	/// If `success` is returned by `body`, the associated value would be
-	/// persisted to `inner`. Otherwise, the failure would be emitted by the
-	/// `validations` signal.
-	///
-	/// - parameters:
-	///   - inner: The inner property to wrap.
-	///   - errorTransform: The error transform for the presentation.
-	///   - body: The closure to invoke for any proposed value to `self`.
-	public convenience init<E: Swift.Error>(
-		_ inner: TransactionalProperty<Value, E>,
-		errorTransform: @escaping (E) -> TransactionError,
-		_ body: @escaping (Value) -> Result<Value, TransactionError>
-	) {
-		self.init(inner, transform: { $0 }, errorTransform: errorTransform, body)
+		let current = inner.value
+		let initialValidation = validator(transform(current)).map { _ in }
+		let _validations = MutableProperty<Result<(), TransactionError>>(initialValidation)
+
+		self.lifetime = inner.lifetime
+		self.validations = Property(capturing: _validations)
+		self.cache = inner.property.cache.map(transform)
+		self.rootBox = inner.property.rootBox
+
+		validationSetup?(_validations)
+
+		action = { input in
+			switch validator(input) {
+			case let .success(innerResult):
+				inner.property.action(innerResult)
+
+			case let .failure(error):
+				_validations.value = .failure(error)
+			}
+		}
 	}
 
 	/// Atomically performs an arbitrary action using the current value of the

	/// - returns: A validating `TransactionalProperty`.
	public func validate<Error: Swift.Error>(
		_ predicate: @escaping (Value) -> Result<(), Error>
		) -> TransactionalProperty<Value, Error> {
		return TransactionalProperty(self) { proposedInput in
			switch predicate(proposedInput) {
			case .success:
				return .success(proposedInput)

			if let value = proposed.swap(nil) {
				property?.value = value
			} else {
				property?.property.revalidate()
			}
		}

