Bird
Raised Fist0
Typescriptprogramming~5 mins

Covariance and contravariance in Typescript - Cheat Sheet & Quick Revision

Choose your learning style10 modes available
Recall & Review
beginner
What is covariance in TypeScript?
Covariance means you can use a more specific type than expected. For example, if a function expects a type, you can give it a subtype. It works like a "child" fitting where a "parent" is expected.
Click to reveal answer
beginner
What is contravariance in TypeScript?
Contravariance means you can use a more general type than expected. For example, if a function expects a subtype, you can give it a supertype. It is like accepting a broader category where a specific one is expected.
Click to reveal answer
intermediate
Explain covariance with function return types.
Function return types are covariant. This means a function that returns a subtype can be used where a function returning a supertype is expected. It is safe because the caller expects a general type but gets a more specific one.
Click to reveal answer
intermediate
Explain contravariance with function parameter types.
Function parameter types are contravariant. This means a function that accepts a supertype can be used where a function expecting a subtype is required. It is safe because the function can handle more general inputs.
Click to reveal answer
beginner
Why is understanding covariance and contravariance important in TypeScript?
It helps you write flexible and safe code. You can substitute types correctly in functions and variables without errors. It also helps understand how TypeScript checks type compatibility.
Click to reveal answer
Which of the following is an example of covariance in TypeScript?
AA function returning a supertype where a subtype is expected
BA function accepting a supertype where a subtype is expected
CA function accepting a subtype where a supertype is expected
DA function returning a subtype where a supertype is expected
Contravariance in TypeScript applies mainly to:
AFunction parameter types
BClass inheritance
CVariable declarations
DFunction return types
If a function expects a parameter of type 'Dog', which parameter type can be used contravariantly?
AAnimal (supertype of Dog)
BDog
CCat (unrelated type)
Dstring
Why is covariance safe for function return types?
ABecause the caller expects a more specific type
BBecause the caller expects a general type and gets a more specific one
CBecause the function accepts more general inputs
DBecause the function accepts more specific inputs
Which statement about TypeScript variance is true?
AFunction parameters are covariant
BFunction return types are contravariant
CFunction parameters are contravariant
DVariables are always invariant
Describe covariance and contravariance in your own words with simple examples.
Think about how types can be substituted in function parameters and return values.
You got /3 concepts.
    Explain why function return types are covariant and function parameter types are contravariant in TypeScript.
    Consider what happens if you give a function a more general or more specific type.
    You got /3 concepts.

      Practice

      (1/5)
      1. Which statement best describes covariance in TypeScript?
      easy
      A. It allows replacing a type with a more specific type safely, mainly in outputs.
      B. It allows replacing a type with a more general type safely, mainly in inputs.
      C. It means types cannot be replaced or changed in any way.
      D. It only applies to primitive types like string and number.

      Solution

      1. Step 1: Understand covariance meaning

        Covariance means you can use a more specific type where a general type is expected, usually for outputs like return values.
      2. Step 2: Compare with contravariance

        Contravariance is about inputs and generalizing types, so it is different from covariance.
      3. Final Answer:

        It allows replacing a type with a more specific type safely, mainly in outputs. -> Option A
      4. Quick Check:

        Covariance = more specific output type [OK]
      Hint: Covariance = output types get more specific [OK]
      Common Mistakes:
      • Confusing covariance with contravariance
      • Thinking covariance applies to inputs
      • Believing covariance restricts type changes
      2. Which of the following TypeScript function types correctly demonstrates contravariance in the parameter type?
      easy
      A. (input: Dog) => void
      B. (input: Animal) => void
      C. (input: string) => void
      D. (input: number) => void

      Solution

      1. Step 1: Understand contravariance in parameters

        Contravariance means a function can accept a more general type as input than expected.
      2. Step 2: Compare parameter types

        Given Dog extends Animal, accepting Animal (more general) instead of Dog is contravariant.
      3. Final Answer:

        (input: Animal) => void -> Option B
      4. Quick Check:

        Contravariance = input type generalizes [OK]
      Hint: Contravariance = input types get more general [OK]
      Common Mistakes:
      • Choosing more specific input types for contravariance
      • Mixing input and output type variance
      • Ignoring inheritance relationships
      3. Consider the following TypeScript code:
      class Animal { name: string = 'animal'; }
      class Dog extends Animal { breed: string = 'bulldog'; }
      
      let func1: (dog: Dog) => Dog = (d) => d;
      let func2: (animal: Animal) => Animal = func1;
      
      const result = func2(new Animal());
      console.log(result.name);

      What will be the output when this code runs?
      medium
      A. animal
      B. bulldog
      C. undefined
      D. Type error at assignment

      Solution

      1. Step 1: Analyze function type assignment

        func1 expects a Dog parameter and returns Dog. Assigning func1 to func2 which expects Animal parameter and returns Animal is invalid because parameter types are contravariant and return types covariant.
      2. Step 2: Understand TypeScript type checking

        TypeScript disallows assigning a function expecting a more specific parameter (Dog) to one expecting a more general parameter (Animal) due to contravariance rules.
      3. Final Answer:

        Type error at assignment -> Option D
      4. Quick Check:

        Contravariance blocks incompatible parameter types [OK]
      Hint: Check parameter types for contravariance errors [OK]
      Common Mistakes:
      • Assuming assignment is allowed without error
      • Ignoring contravariance in function parameters
      • Expecting runtime output instead of compile error
      4. The following TypeScript code causes a type error. What is the main cause?
      interface Producer<out T> {
        produce: () => T;
      }
      
      interface Consumer<in T> {
        consume: (item: T) => void;
      }
      
      let producer: Producer<Animal> = { produce: () => new Animal() };
      let consumer: Consumer<Dog> = { consume: (d) => console.log(d.breed) };
      
      consumer = producer; // Error here
      medium
      A. Dog does not extend Animal, so types are incompatible.
      B. The produce method is missing a return type.
      C. Assigning Producer<Animal> to Consumer<Dog> is invalid due to variance mismatch.
      D. The consume method should return a value.

      Solution

      1. Step 1: Identify variance roles

        Producer is covariant (outputs), Consumer is contravariant (inputs). Assigning producer to consumer mixes these roles incorrectly.
      2. Step 2: Understand type incompatibility

        Producer<Animal> cannot be assigned to Consumer<Dog> because their variance directions conflict, causing a type error.
      3. Final Answer:

        Assigning Producer<Animal> to Consumer<Dog> is invalid due to variance mismatch. -> Option C
      4. Quick Check:

        Variance mismatch causes assignment error [OK]
      Hint: Match variance directions when assigning generic types [OK]
      Common Mistakes:
      • Ignoring variance annotations (in/out)
      • Assuming unrelated interfaces can be assigned
      • Confusing input and output roles
      5. You want to create a TypeScript function that accepts a callback which can handle any subtype of Animal as input and returns a more specific subtype of Animal. Which function type signature correctly uses covariance and contravariance to allow this flexibility?
      hard
      A. function processAnimal(callback: (input: Animal) => Dog): Dog
      B. function processAnimal(callback: (input: Dog) => Animal): Animal
      C. function processAnimal(callback: (input: Animal) => Animal): Dog
      D. function processAnimal(callback: (input: Dog) => Dog): Animal

      Solution

      1. Step 1: Identify input contravariance

        The callback input should be a general type (Animal) to accept any subtype safely (contravariance).
      2. Step 2: Identify output covariance

        The callback returns a more specific subtype (Dog), allowing covariance in the return type.
      3. Step 3: Match function signature

        function processAnimal(callback: (input: Animal) => Dog): Dog matches these rules: input is Animal (general), output is Dog (specific), and the function returns Dog.
      4. Final Answer:

        function processAnimal(callback: (input: Animal) => Dog): Dog -> Option A
      5. Quick Check:

        Input general, output specific = contravariant input, covariant output [OK]
      Hint: Input general, output specific for flexible callbacks [OK]
      Common Mistakes:
      • Reversing input and output types
      • Using more specific input types causing errors
      • Ignoring return type covariance
      Recommended

      Ready to prove it?

      Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

      10 questions~5 mineasy hard