Equivalencia desde Kotlin
Genéricos y varianza
AproximadaTypeScript sigue siendo estructuralmente tipado incluso con anotaciones de varianza: in y out documentan y validan la varianza pretendida del parámetro de tipo, pero no vuelven nominal al tipo genérico ni cambian en general el resto de las comparaciones estructurales. La sintaxis de método (accept(value: T): void) retiene una excepción de bivarianza histórica y acepta asignaciones que no son sólidas; una propiedad de tipo función (accept: (value: T) => void) recibe una comprobación contravariante estricta bajo strictFunctionTypes, y rechaza esa misma asignación insegura.
Referencia Kotlin: Source<out T> es covariante y Sink<in T> es contravariante.
- Mecanismo
- anotaciones de varianza
in/outsobre compatibilidad estructural - Idea conservada
- Source<out T> es covariante: un Source<Dog> es utilizable donde se requiere un Source<Animal>. Sink<in T> es contravariante: un Sink<Animal> es utilizable donde se requiere un Sink<Dog>.
- Riesgo de diseño
- Suponer que anotar in/out vuelve nominal la comparación de tipos, o declarar un consumidor con sintaxis de método esperando la misma comprobación estricta que una propiedad de tipo función.
- Recomendación
- Declara consumidores como propiedades de tipo función cuando strictFunctionTypes deba rechazar asignaciones insalubres; usa sintaxis de método solo cuando la excepción de bivarianza sea intencional.
- Convención del curso
- No agregues in/out a un genérico salvo que la varianza sea parte del contrato que se enseña.
- Mecanismo del lenguaje
- Anotaciones
in/outen la declaración del parámetro de tipo.
Diferencias relevantes
- Las anotaciones in/out documentan y validan la varianza pretendida; TypeScript ya infiere la varianza estructuralmente incluso sin ellas en la mayoría de los casos.
- La excepción de bivarianza solo aplica a miembros declarados con sintaxis de método, no a propiedades de tipo función.
Source<out T> es covariante, Sink<in T> es contravariante.
export interface Animal {
readonly name: string;
}
export interface Dog extends Animal {
readonly breed: string;
}
export interface Source<out T> {
readonly get: () => T;
}
export interface Sink<in T> {
readonly accept: (value: T) => void;
}
/** Function-valued property: checked contravariantly (strictly) under strictFunctionTypes. */
export interface FunctionPropertySink<T> {
readonly accept: (value: T) => void;
}
/** The same shape declared with method syntax retains the bivariance exception. */
export interface MethodSink<T> {
accept(value: T): void;
}