diff --git a/util.go b/util.go
index fb7fa788..bdfa886b 100644
--- a/util.go
+++ b/util.go
@@ -9,6 +9,13 @@ import (
 	"time"
 )
 
+// Valuer is an interface that allows you to expose a method on a type
+// (including generic types) that returns a value that is supposed to be validated.
+type Valuer interface {
+	// ValidatorValue returns the value that is supposed to be validated.
+	ValidatorValue() any
+}
+
 // extractTypeInternal gets the actual underlying type of field value.
 // It will dive into pointers, customTypes and return you the
 // underlying value and it's kind.
@@ -23,6 +30,13 @@ BEGIN:
 			return current, reflect.Ptr, nullable
 		}
 
+		if current.CanInterface() {
+			if v, ok := current.Interface().(Valuer); ok {
+				current = reflect.ValueOf(v.ValidatorValue())
+				goto BEGIN
+			}
+		}
+
 		current = current.Elem()
 		goto BEGIN
 
@@ -34,6 +48,13 @@ BEGIN:
 			return current, reflect.Interface, nullable
 		}
 
+		if current.CanInterface() {
+			if v, ok := current.Interface().(Valuer); ok {
+				current = reflect.ValueOf(v.ValidatorValue())
+				goto BEGIN
+			}
+		}
+
 		current = current.Elem()
 		goto BEGIN
 
@@ -42,6 +63,13 @@ BEGIN:
 
 	default:
 
+		if current.CanInterface() {
+			if v, ok := current.Interface().(Valuer); ok {
+				current = reflect.ValueOf(v.ValidatorValue())
+				goto BEGIN
+			}
+		}
+
 		if v.v.hasCustomFuncs {
 			if fn, ok := v.v.customFuncs[current.Type()]; ok {
 				current = reflect.ValueOf(fn(current))
diff --git a/validator_test.go b/validator_test.go
index 85284ecc..49bb1ee7 100644
--- a/validator_test.go
+++ b/validator_test.go
@@ -14319,3 +14319,221 @@ func TestValidateFn(t *testing.T) {
 		Equal(t, fe.Tag(), "validateFn")
 	})
 }
+
+type ValuerTypeWithPointerReceiver[T any] struct {
+	Data T
+}
+
+func (t *ValuerTypeWithPointerReceiver[T]) ValidatorValue() any {
+	return t.Data
+}
+
+type ValuerTypeWithValueReceiver[T any] struct {
+	Data T
+}
+
+func (t ValuerTypeWithValueReceiver[T]) ValidatorValue() any {
+	return t.Data
+}
+
+func TestValuerInterface(t *testing.T) {
+	t.Run("parent as Valuer (not called)", func(t *testing.T) {
+		errs := New().Struct(&ValuerTypeWithPointerReceiver[SubTest]{})
+		AssertError(t, errs,
+			"ValuerTypeWithPointerReceiver[github.com/go-playground/validator/v10.SubTest].Data.Test",
+			"ValuerTypeWithPointerReceiver[github.com/go-playground/validator/v10.SubTest].Data.Test",
+			"Test", "Test", "required")
+	})
+	t.Run("pointer parent, pointer nested, pointer receiver (called)", func(t *testing.T) {
+		type Parent struct {
+			Nested *ValuerTypeWithPointerReceiver[SubTest] `validate:"required"`
+		}
+
+		errs := New().Struct(&Parent{})
+		AssertError(t, errs, "Parent.Nested", "Parent.Nested", "Nested", "Nested", "required")
+
+		errs = New().Struct(&Parent{
+			Nested: &ValuerTypeWithPointerReceiver[SubTest]{},
+		})
+		AssertError(t, errs, "Parent.Nested.Test", "Parent.Nested.Test", "Test", "Test", "required")
+
+		errs = New().Struct(&Parent{
+			Nested: &ValuerTypeWithPointerReceiver[SubTest]{
+				Data: SubTest{
+					Test: "Test",
+				},
+			},
+		})
+		if errs != nil {
+			t.Fatalf("Expected no error, got: %v", errs)
+		}
+	})
+	t.Run("pointer parent, pointer nested, value receiver (called)", func(t *testing.T) {
+		type Parent struct {
+			Nested *ValuerTypeWithValueReceiver[SubTest] `validate:"required"`
+		}
+
+		errs := New().Struct(&Parent{})
+		AssertError(t, errs, "Parent.Nested", "Parent.Nested", "Nested", "Nested", "required")
+
+		errs = New().Struct(&Parent{
+			Nested: &ValuerTypeWithValueReceiver[SubTest]{},
+		})
+		AssertError(t, errs, "Parent.Nested.Test", "Parent.Nested.Test", "Test", "Test", "required")
+
+		errs = New().Struct(&Parent{
+			Nested: &ValuerTypeWithValueReceiver[SubTest]{
+				Data: SubTest{
+					Test: "Test",
+				},
+			},
+		})
+		if errs != nil {
+			t.Fatalf("Expected no error, got: %v", errs)
+		}
+	})
+	t.Run("pointer parent, value nested, pointer receiver (not called)", func(t *testing.T) {
+		type Parent struct {
+			Nested ValuerTypeWithPointerReceiver[SubTest] `validate:"required"`
+		}
+
+		errs := New().Struct(&Parent{})
+		AssertError(t, errs, "Parent.Nested.Data.Test", "Parent.Nested.Data.Test", "Test", "Test", "required")
+
+		errs = New().Struct(&Parent{
+			Nested: ValuerTypeWithPointerReceiver[SubTest]{},
+		})
+		AssertError(t, errs, "Parent.Nested.Data.Test", "Parent.Nested.Data.Test", "Test", "Test", "required")
+
+		errs = New().Struct(&Parent{
+			Nested: ValuerTypeWithPointerReceiver[SubTest]{
+				Data: SubTest{
+					Test: "Test",
+				},
+			},
+		})
+		if errs != nil {
+			t.Fatalf("Expected no error, got: %v", errs)
+		}
+	})
+	t.Run("pointer parent, value nested, value receiver (called)", func(t *testing.T) {
+		type Parent struct {
+			Nested ValuerTypeWithValueReceiver[SubTest] `validate:"required"`
+		}
+
+		errs := New().Struct(&Parent{})
+		AssertError(t, errs, "Parent.Nested.Test", "Parent.Nested.Test", "Test", "Test", "required")
+
+		errs = New().Struct(&Parent{
+			Nested: ValuerTypeWithValueReceiver[SubTest]{},
+		})
+		AssertError(t, errs, "Parent.Nested.Test", "Parent.Nested.Test", "Test", "Test", "required")
+
+		errs = New().Struct(&Parent{
+			Nested: ValuerTypeWithValueReceiver[SubTest]{
+				Data: SubTest{
+					Test: "Test",
+				},
+			},
+		})
+		if errs != nil {
+			t.Fatalf("Expected no error, got: %v", errs)
+		}
+	})
+	t.Run("value parent, pointer nested, pointer receiver (called)", func(t *testing.T) {
+		type Parent struct {
+			Nested *ValuerTypeWithPointerReceiver[SubTest] `validate:"required"`
+		}
+
+		errs := New().Struct(Parent{})
+		AssertError(t, errs, "Parent.Nested", "Parent.Nested", "Nested", "Nested", "required")
+
+		errs = New().Struct(Parent{
+			Nested: &ValuerTypeWithPointerReceiver[SubTest]{},
+		})
+		AssertError(t, errs, "Parent.Nested.Test", "Parent.Nested.Test", "Test", "Test", "required")
+
+		errs = New().Struct(Parent{
+			Nested: &ValuerTypeWithPointerReceiver[SubTest]{
+				Data: SubTest{
+					Test: "Test",
+				},
+			},
+		})
+		if errs != nil {
+			t.Fatalf("Expected no error, got: %v", errs)
+		}
+	})
+	t.Run("value parent, pointer nested, value receiver (called)", func(t *testing.T) {
+		type Parent struct {
+			Nested *ValuerTypeWithValueReceiver[SubTest] `validate:"required"`
+		}
+
+		errs := New().Struct(Parent{})
+		AssertError(t, errs, "Parent.Nested", "Parent.Nested", "Nested", "Nested", "required")
+
+		errs = New().Struct(Parent{
+			Nested: &ValuerTypeWithValueReceiver[SubTest]{},
+		})
+		AssertError(t, errs, "Parent.Nested.Test", "Parent.Nested.Test", "Test", "Test", "required")
+
+		errs = New().Struct(Parent{
+			Nested: &ValuerTypeWithValueReceiver[SubTest]{
+				Data: SubTest{
+					Test: "Test",
+				},
+			},
+		})
+		if errs != nil {
+			t.Fatalf("Expected no error, got: %v", errs)
+		}
+	})
+	t.Run("value parent, value nested, pointer receiver (not called)", func(t *testing.T) {
+		type Parent struct {
+			Nested ValuerTypeWithPointerReceiver[SubTest] `validate:"required"`
+		}
+
+		errs := New().Struct(Parent{})
+		AssertError(t, errs, "Parent.Nested.Data.Test", "Parent.Nested.Data.Test", "Test", "Test", "required")
+
+		errs = New().Struct(Parent{
+			Nested: ValuerTypeWithPointerReceiver[SubTest]{},
+		})
+		AssertError(t, errs, "Parent.Nested.Data.Test", "Parent.Nested.Data.Test", "Test", "Test", "required")
+
+		errs = New().Struct(Parent{
+			Nested: ValuerTypeWithPointerReceiver[SubTest]{
+				Data: SubTest{
+					Test: "Test",
+				},
+			},
+		})
+		if errs != nil {
+			t.Fatalf("Expected no error, got: %v", errs)
+		}
+	})
+	t.Run("value parent, value nested, value receiver (called)", func(t *testing.T) {
+		type Parent struct {
+			Nested ValuerTypeWithValueReceiver[SubTest] `validate:"required"`
+		}
+
+		errs := New().Struct(Parent{})
+		AssertError(t, errs, "Parent.Nested.Test", "Parent.Nested.Test", "Test", "Test", "required")
+
+		errs = New().Struct(Parent{
+			Nested: ValuerTypeWithValueReceiver[SubTest]{},
+		})
+		AssertError(t, errs, "Parent.Nested.Test", "Parent.Nested.Test", "Test", "Test", "required")
+
+		errs = New().Struct(Parent{
+			Nested: ValuerTypeWithValueReceiver[SubTest]{
+				Data: SubTest{
+					Test: "Test",
+				},
+			},
+		})
+		if errs != nil {
+			t.Fatalf("Expected no error, got: %v", errs)
+		}
+	})
+}