diff --git a/type_manipulation.go b/type_manipulation.go index 45d8fe20..ac31c0f5 100644 --- a/type_manipulation.go +++ b/type_manipulation.go @@ -7,6 +7,12 @@ func ToPtr[T any](x T) *T { return &x } +// IsNil checks if a value is nil or if it's a reference type with a nil underlying value. +func IsNil(x any) bool { + defer func() { recover() }() + return x == nil || reflect.ValueOf(x).IsNil() +} + // EmptyableToPtr returns a pointer copy of value if it's nonzero. // Otherwise, returns nil pointer. func EmptyableToPtr[T any](x T) *T { diff --git a/type_manipulation_test.go b/type_manipulation_test.go index 48e3676f..ee4fa42e 100644 --- a/type_manipulation_test.go +++ b/type_manipulation_test.go @@ -15,6 +15,30 @@ func TestToPtr(t *testing.T) { is.Equal(*result1, []int{1, 2}) } +func TestIsNil(t *testing.T) { + t.Parallel() + is := assert.New(t) + + var x int + is.False(IsNil(x)) + + var k struct{} + is.False(IsNil(k)) + + var s *string + is.True(IsNil(s)) + + var i *int + is.True(IsNil(i)) + + var b *bool + is.True(IsNil(b)) + + var ifaceWithNilValue interface{} = (*string)(nil) + is.True(IsNil(ifaceWithNilValue)) + is.True(ifaceWithNilValue != nil) +} + func TestEmptyableToPtr(t *testing.T) { t.Parallel() is := assert.New(t)