Cannot pass PartialKeyPath<T> to generic function

I'm having problems calling this method:

public struct Validation
{
  public static func register<declaringT : Object, propertyT, contextT : Object>(keyPath: PartialKeyPath<declaringT>, closure: @escaping ValidatorClosure<declaringT, propertyT, contextT>)
  {
   …
  }
  
  …
}

The calling code is:

extension Person : StaticInitialisable
{
  public static var staticInit: (() -> ())? =
  {
    Validation.register(keyPath: \Person.name)
    {
      owner, args, context in

      if args.newValue == nil
      {
        args.Message = "The name of a Person cannot be nil. Do you wish to continue?";

        args.ErrorSeverity = ValidationErrorSeverity.Confirm;
      }
    }
  }
}

I was hoping that, by passing a PartialKeyPath to the receiving method, it would be enough to infer the type.

I even explicitly typed the input parameters to the closure in the hope that that would work but, no joy.

extension Person : StaticInitialisable
{
  public static var staticInit: (() -> ())? =
  {
    Validation.register(keyPath: \Person.name)
    {
      (owner: Person, args, context: Person) -> ()

      if args.newValue == nil
      {
        args.Message = "The name of a Person cannot be nil. Do you wish to continue?";

        args.ErrorSeverity = ValidationErrorSeverity.Confirm;
      }
    }
  }
}

Any ideas please?

What is Object? What is ValidatorClosure? What is Person? What is StaticInitialisable? What error message is the compiler giving you? It's difficult to help when I can't reproduce your problem on my machine.

2 Likes

ValidatorClosure<declaringT, propertyT, contextT> is an alias for (subjectT, ValidationEventArgs<propertyT>, contextT) -> ()

Person is a subclass of Object, which is a base class, the details of which are not relevant to this code.

StaticInitialisable is a protocol, which has the one static var staticInit which holds a parameterless closure.

And the error is:

    Validation.register(keyPath: \Person.name) // error : Type '_' has no member 'name' 
    {
      (owner: Person, args, context: Person) -> ()
      
      …
    }

Solved !!!

The Validation method signature should be:

public struct Validation
{
  public static func register<declaringT : Object, propertyT, contextT : Object>(keyPath: KeyPath<declaringT, propertyT>, closure: @escaping ValidatorClosure<declaringT, propertyT, contextT>)
  {
    …
  }

Thanks for the "rubber duck consultancy™"

I'm glad you solved your problem. Next time please try to reduce your problem to a Minimal, Complete and Verifiable example to make it easier for others to help you. :slight_smile:

2 Likes