Great article is rare see people showing SOLID with functions (in not a functional way), but there are few things wrong.
The OCP is wrong, in that example you aren't extending the base object, you're modifiyng it soo breaking the OCP.
A better approach is pass objects tied by the same contract instead of an object with a type property, as in this way you'll be using polymorphism to handle the dynamic dispatch instead of implementing coupling a function to an object.
In the LSP example you're breaking the principle too. Your example makes the function depend on a union type, but the LSP is a complement to the DIP as the goal is make the sub-types behave like the base types, and a sub-types are intersection types not union types.
By making the sub-types behave like the original you can pass they interchangeably without the need of a caution because if one thing exist and behave in the base, It is the same in the sub-type. A union type goes in the oposite direction by making a function depend on a value that can be different.
Other approach you could do is in the function type instead of the param type, by applying the ideas of contravariance and covariance.
And the DIP example is good, but instead of implementing a interface-like mechanism, you could just made the function depend of other function, this effectly could have made the function depend on other abstract thing that is other function signature.
The notify function still breaks the principle as it is coupled with the function that gets the contact, that is a concrete module, receiving that as a param should fix this.
around me
Online Business
Its a very nice article knowledgeable. Aroundme Directory. Looking forward to participate in helpful discussion.