Duck typing is used in object-oriented languages when the programmer is interested only in the default behaviour of an object rather than the class as a whole.
When duck typing is not used, the dependancy of one class on another is much greater and thus breaks the principle of dependency inversion. However, when duck typing is used, the dependency is reduced.
An example of this could be if there was a class Report which created reports and then contains a method which prints the reports.
Without duck typing:
class Report 
  def body 
     generatereportystuff 
  end
  def print 
     JSONFormatter.new.format(body) 
  end 
end
class JSONFormatter 
  def format(body) 
     ... 
  end 
end
As you can see in the above example, the print method is dependant on the JSONFormatter class as it is creating a new instance of this. Therefore it does't abide by the SOLID principles.
Below you can see the same code, but this time with duck typing.
class Report 
  def body 
     generatereportystuff 
  end
  def print(formatter: JSONFormatter.new) 
     formatter.format body 
  end 
end
This code is much more clearer and less dependant on the JSONFormatter. We can now pass any type of formatter to our print method and it will work rather than break.
A quote which may make duck typing easier to understand; "If it looks like a duck and quacks like a duck, it's a duck".
Usman & Zhivko