I'm trying to create a generic function that checks whether a record is in a valid format, given the record implements the static member valid. When trying to use this in an ElmishComponent within the Bolero (Blazor) framework, I'm getting the following error
This code is not sufficiently generic. The type variable ^childModel when ^childModel : (static member valid : ^childModel -> bool) could not be generalized because it would escape its scope
With the following code
module Modal =
type Message<'childModel, 'childMessage> = | Confirm of 'childModel | Cancel | ChildMessage of 'childMessage
type Model<'T> = { Display : bool; Title : string; Child : 'T }
let inline valid (x: ^t) =
(^t: (static member valid: ^t -> bool) (x))
type Component<'T, ^childModel, 'childMessage when 'T :> ElmishComponent< ^childModel, 'childMessage> and ^childModel : (static member valid: ^childModel -> bool)>() =
inherit ElmishComponent<Model<'childModel>, Message<'childModel, 'childMessage>>()
// Error is highlighted on this line
override this.View model dispatch =
cond model.Display <| function
| true ->
div [ attr.style (if model.Display then "background: lightblue;" else "background: grey;") ] [
h3 [] [ text model.Title ]
ecomp<'T,_,_> model.Child (dispatch << ChildMessage)
p [] []
button [
// This is where I use the valid function
attr.disabled (if valid model.Child then null else "true")
on.click (fun _ -> dispatch <| Confirm model.Child)
] [ text "Confirm" ]
button [ on.click (fun _ -> dispatch Cancel) ] [ text "Cancel" ]
]
| false ->
empty
I may be missing something, but it seems to me that a simpler approach would be to use an interface that the child model implements - then you do not have to bother with static member constraints at all:
type IValidable =
abstract IsValid : bool
type Component<'T, 'childModel, 'childMessage when
'T :> ElmishComponent< 'childModel, 'childMessage> and
'childModel :> IValidable>() =
inherit ElmishComponent<Model<'childModel>, Message<'childModel, 'childMessage>>()
override this.View model dispatch =
let test = model.Child.IsValid
()