Estudei recentemente os conceitos genéricos em Typescript. Tenho um problema em entender "Por que as funções contravariância com seus parâmetros?" . Eu sei que:
Covariance
é seT extends U
(T
é atribuível aU
), é verdade queG<T> extends G<U>
(G<T>
também é atribuível aG<U>
)Contravariance
é seT extends U
, é certo concluir queG<U> extends G<T>
(agoraG<U>
é atribuível aG<T>
).
antes de fazer a pergunta neste fórum, li as seguintes postagens. No entanto, ainda tenho dificuldade em entender por que as funções no Typescript são contravariantes em seus parâmetros :
- Por que o tipo de acesso indexado usando genéricos resulta em interseção?
- O que são covariância e contravariância?
- Diferença entre Variância, Covariância, Contravariância, Bivariância e Invariância em TypeScript
- Covariância e Contravariância em TypeScript
Vejo que não apenas funções são contravariantes com seus parâmetros em TypeScript, mas algumas outras linguagens também são verdadeiras.
Sinto-me tão frustrado por aceitar isso sem descobrir por que é verdade. Você poderia me ajudar a explicar ou se eu estiver faltando conhecimento relacionado, por favor me diga o que é.
Usarei o exemplo concreto de
Animal
eDog
.Há duas opções para permitir a atribuição entre
Dog
eAnimal
, podemos substituirDog
porAnimal
e podemos substituirAnimal
porDog
.Porque
extends
significa que temos os membros da base, isso é bom. O Typescript permite issoNão há um
bark
método emAnimal
, então isso falharia em tempo de execução. Typescript proíbe isso.Agora vamos dar uma olhada nos tipos de função.
Os designers de linguagem têm a mesma escolha sobre parâmetros de função. Vamos ver o que acontece quando permitimos os dois casos
Porque estamos passando um
Dog
parauseAnimal
ele está bom, podemove(10)
como acima. Typescript permite isso.O
Animal
we pass touseDog
causaria uma falha de tempo de execução, porque faltabark()
. Typescript proíbe isso.