И о чём этот пример говорит? Что spread оператор сбрасывает аннотации?
class Animal {
genus: number = 0
}
class Cat extends Animal {
clawSize: number = 0
}
type ContravariantMethod<in V> = {
process(v: V): void;
}
declare let _processCat_: ContravariantMethod<Cat>
declare let _processAnimal_: ContravariantMethod<Animal>
let processAnimal = (animal: Animal) => {}
let processCat = (cat: Cat) => {}
_processAnimal_ = _processCat_ // Ошибка
_processCat_ = _processAnimal_ // Ок
_processAnimal_ = { ..._processCat_ } // Снова ок, но потому что typescript сбросил аннотацию
processAnimal = processCat // Ошибка
processCat = processAnimal // Ок
processAnimal = { ...processCat } // Всё ещё ошибка, потому что функции всегда контравариантны
Вот буквально вырезка из этой же документации, которая приводит в пример эту же ситуацию, и прямо заявляет, что "measurement can be inaccurate"
Because variance is a naturally emergent property of structural types, TypeScript automatically infers the variance of every generic type. In extremely rare cases involving certain kinds of circular types, this measurement can be inaccurate. If this happens, you can add a variance annotation to a type parameter to force a particular variance:
Прекрасно сказано: "Никогда не используйте аннотации вариантности которые не совпадают со структурной вариантностью типа".
По вашему мой пример выше это НАРУШЕНИЕ структурной вариантности? Изменение вариантность с бивариантной, которую в области вариантности можно воспринять как any, которая в примере выше создают runtime ошибку, на контравариантность - стандартное поведение TypeScript с функциями, что от ошибки избавляет.
Какое тогда по вашему мнению правильное использование аннотаций, которое не меняет тайпчекер?
Документация предостерегает к необдуманному использованию, это верно. Однако, в случае что я привёл, прямо видно проблему которую создают бивариантные методы. Следующий код, являясь переписанной на классы аналогией секции про контраварианты, ошибку больше не показывает: TypeScript playground
class AnimalFood {
protein: number = 0
}
class CatFood extends AnimalFood {
fishness: number = 0
}
abstract class Processor {
abstract process(food: AnimalFood): void;
}
class AnimalProcessor {
process(food: AnimalFood) {}
}
class CatProcessor {
process(food: CatFood) {}
}
const animalProcessor = new AnimalProcessor()
const catProcessor = new CatProcessor()
/**
* Перед подачей обработаем корм
*/
function serveAnimalFood(processor: AnimalProcessor): void {
const food = new AnimalFood();
processor.process(food);
}
function serveCatFood(processor: CatProcessor): void {
const food = new CatFood();
processor.process(food);
}
// оказывается, теперь всем по нраву рыбный вкус
serveAnimalFood(catProcessor);
serveCatFood(animalProcessor);
Так что аннотации вариантности нужны именно для таких случаев. Тут in аннотация увеличит безопасность кода и предостережет от ошибки. Для этого они и созданы.
Информация
В рейтинге
Не участвует
Откуда
Москва, Москва и Московская обл., Россия
Дата рождения
Зарегистрирован
Активность
Специализация
Фронтенд разработчик, Архитектор программного обеспечения
И о чём этот пример говорит? Что spread оператор сбрасывает аннотации?
Вот буквально вырезка из этой же документации, которая приводит в пример эту же ситуацию, и прямо заявляет, что "measurement can be inaccurate"
Прекрасно сказано: "Никогда не используйте аннотации вариантности которые не совпадают со структурной вариантностью типа".
По вашему мой пример выше это НАРУШЕНИЕ структурной вариантности? Изменение вариантность с бивариантной, которую в области вариантности можно воспринять как
any, которая в примере выше создают runtime ошибку, на контравариантность - стандартное поведение TypeScript с функциями, что от ошибки избавляет.Какое тогда по вашему мнению правильное использование аннотаций, которое не меняет тайпчекер?
Документация предостерегает к необдуманному использованию, это верно. Однако, в случае что я привёл, прямо видно проблему которую создают бивариантные методы. Следующий код, являясь переписанной на классы аналогией секции про контраварианты, ошибку больше не показывает:
TypeScript playground
Так что аннотации вариантности нужны именно для таких случаев. Тут
inаннотация увеличит безопасность кода и предостережет от ошибки. Для этого они и созданы.