yoklainterview sim

Frontend Typescript Narrowing Control Flow Interview Questions

75 verified Frontend Typescript Narrowing Control Flow interview questions — solve with answers, learn from explanations, test yourself in a real simulation.

Try the real simulation →

Sample questions

Typescript Narrowing Control FlowDifficulty 1
In TypeScript, what does a typeof x === "string" check inside an if block do to the type of x for the rest of that block?
  • aNothing — TypeScript never changes a variable's type based on runtime checks
  • bNarrows x's type to string for the rest of that block
  • cConverts x to a string at runtime, changing its actual value
  • dRemoves the type annotation from x entirely
Explanation:This is TypeScript's core narrowing mechanism: a typeof check is one of several recognized type guards. Inside the branch where the check is true, the compiler statically narrows the variable's type to string for all code within that block, so string-only methods become available without a cast.
Typescript Narrowing Control FlowDifficulty 1
class Dog { bark(): void {} }
class Cat { meow(): void {} }

function speak(pet: Dog | Cat) {
  if (pet instanceof Dog) {
    pet.bark();
  } else {
    pet.meow();
  }
}

Does this compile without error?
  • aNo — instanceof cannot be used to narrow a union of two classes
  • bNo — pet.meow() is unreachable and TypeScript flags it as an error
  • cYes — instanceof narrows pet to Cat in the else branch, so meow() is valid
  • dYes, but only if both classes share a common base class
Explanation:instanceof is a standard narrowing guard. In the if branch, pet narrows to Dog, so bark() is valid. Since the union has only two members, TypeScript can conclude the else branch means pet must be Cat, narrowing it accordingly — no shared base class is required.
Typescript Narrowing Control FlowDifficulty 1
function total(value: number | number[]) {
  if (Array.isArray(value)) {
    return value.reduce((a, b) => a + b, 0);
  }
  return value * 2;
}

What does Array.isArray(value) do for the type of value inside the if block?
  • aNarrows value to number[], so array methods like reduce are valid
  • bHas no effect on the type; a manual cast is still required to call reduce
  • cNarrows value to any[], losing the number element type
  • dOnly works at runtime and causes a compile error on reduce
Explanation:Array.isArray is a built-in type guard recognized by TypeScript. Inside the if block it narrows value from number | number[] down to number[], so array methods are usable directly with full type information (elements are known to be number).
Typescript Narrowing Control FlowDifficulty 1
function greet(name: string | undefined) {
  if (name) {
    console.log(name.toUpperCase());
  }
}

Inside the if block, what is the narrowed type of name?
  • astring | undefined, unchanged
  • bundefined
  • cunknown
  • dstring
Explanation:A plain truthiness check (if (name)) is a recognized narrowing pattern: it excludes falsy values, which for string | undefined means excluding undefined (and the empty string "", though that doesn't remove a type here). The remaining type inside the block is string.
Typescript Narrowing Control FlowDifficulty 1
type Cat = { meow(): void };
type Robot = { beep(): void };

function activate(entity: Cat | Robot) {
  if ("meow" in entity) {
    entity.meow();
  } else {
    entity.beep();
  }
}

What narrows entity to Cat in the if branch?
  • aTypeScript cannot narrow object-type unions this way; this is a compile error
  • bThe in operator, checking whether the "meow" property exists on the object's type
  • cTypeScript infers it from the variable's name entity
  • dIt only works because Cat and Robot both have exactly one method
Explanation:The in operator is a recognized narrowing guard for object types: "prop" in obj checks, at the type level, which union member(s) declare that property. Since only Cat has meow, TypeScript narrows entity to Cat in the if branch and to Robot in the else.
Typescript Narrowing Control FlowDifficulty 1
A function accepts id: string | number and needs to call .toFixed(2), which only exists on number. What is the correct way to make this compile?
  • aCast id to number with as number without checking anything first
  • bCall .toFixed(2) directly; TypeScript will auto-convert string at runtime
  • cCheck typeof id === "number" first, then call .toFixed(2) inside that branch
  • dChange the parameter type to any so all method calls are allowed
Explanation:The idiomatic approach is a type guard: typeof id === "number" narrows id to number inside that branch, making .toFixed(2) valid without a cast. Blind casting (as number) suppresses the check instead of proving it, and any throws away type safety entirely.

Test yourself against the 2925-question Frontend bank.

Start interview