В разделе "Обобщения / Модификаторы вариантности параметров типа in и out" говорится:
in указывает, что параметр типа ковариантен, а out контрвариантен. Но стоит сделать акцент на том, что с помощью этих модификаторов невозможно изменить правила по которым TypeScript производит вычисления совместимости, а можно лишь их конкретизировать.
На самом же деле, модификаторы вариантности могут сужать вариантность, но не могут её расширять или менять на противоположную. То есть, если параметр типа автоматически выводится ковариантным, мы можем сделать его инвариантным, но не можем сделать бивариантным или контравариантным. Бивариантному параметру можно установить любую желаемую вариантность.
Пример:
// Здесь параметр T является бивариантным
type Example<T> = {}
declare let vsub: Example<1>
declare let vsuper: Example<1 | 2>
// Присваивание в обе стороны возможно
vsub = vsuper
vsuper = vsub
// Здесь параметр T является контравариантным
type Example<in T> = {}
declare let vsub: Example<1>
declare let vsuper: Example<1 | 2>
vsub = vsuper
vsuper = vsub // Ошибка
Если нужно, могу привести реальные примеры в которых это позволяет избежать ошибок.
В разделе "Обобщения / Модификаторы вариантности параметров типа in и out" говорится:
На самом же деле, модификаторы вариантности могут сужать вариантность, но не могут её расширять или менять на противоположную. То есть, если параметр типа автоматически выводится ковариантным, мы можем сделать его инвариантным, но не можем сделать бивариантным или контравариантным. Бивариантному параметру можно установить любую желаемую вариантность.
Пример:
Если нужно, могу привести реальные примеры в которых это позволяет избежать ошибок.