What you're referring to is known as row polymorphism or structural typing and it exists in languages such as Elm, Purescript, Scala and Go (and I believe Haskell has these as an extension). For instance, this is valid Scala:
def isOld(thing: {def age: Int}): Boolean =
thing.age > 30
case class Person(name: String, age: Int)
case class Dog(age: Int)
println(isOld(Person("Jim", 25))
println(isOld(Dog(31))
And here's Elm: isOld : {age: Int | a} -> Bool
isOld thing = thing.age > 30
Debug.log (isOld {name: "Jim", age: 42})
Debug.log (isOld {age: 10})