Что такое утиная типизация
Что проверяют
Понимаете ли вы, что в JavaScript пригодность объекта определяется набором его свойств, а не происхождением от класса. Для фронтендера это не отвлечённая теория: половина платформенных интерфейсов устроена именно так, и система типов поверх них тоже структурная.
Как отвечать
Утиная типизация это проверка по поведению: если у объекта есть нужные свойства и методы, он подходит, независимо от того, каким конструктором создан. В браузере на этом держатся сложившиеся протоколы: объект с методом then любой await примет за промис, объект с Symbol.iterator пойдёт в for...of и в спред, объект с полем length и числовыми ключами превратится в массив через Array.from.
Дальше стоит развести два уровня. В рантайме это утиная типизация: наличие свойства выясняется в момент вызова. В TypeScript это структурная типизация: совместимость проверяется по форме на этапе сборки, номинальных типов в языке нет, и объект подойдёт под интерфейс, который он нигде не упоминает.
Плюс такого подхода в гибкости и отсутствии лишних адаптеров. Минус в том, что ошибка всплывает в момент вызова, а стек указывает на место использования, а не на источник плохого объекта.
Где спотыкаются
Проверяют тип через instanceof. У каждого окна и вложенного фрейма свой набор конструкторов, поэтому массив из соседнего фрейма проверку не пройдёт: работают Array.isArray и проверка нужного метода.
Считают, что типы спасают от плохих данных. Проверка формы живёт только внутри сборки: ответ сервера типизируется утверждением, и никакой проверки в рантайме за этим нет, нужна схема и разбор ответа.
Подменяют утиными проверками отсутствующий контракт. Функция перебирает, есть ли у аргумента render, потом template, потом html, и это уже не гибкость, а необъявленный интерфейс, который каждый вызывающий понимает по-своему.