We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.

This lesson's interactive features are locked, please to keep using them

Mapped Types With Conditionals

So if mapped types are a step down the road to type tom-foolery, conditional mapped types are one more leap. I'm not saying they're not cool, or that they're not useful (they are in certain scenarios), but you can create some really hard to read code if you're not careful. So use them wisely.

Let's take our OptionalSoldier example from before:

type Soldier = {
  name: string;
  age: number;
  branch: "garrison" | "military police" | "survey corps";
};

type OptionalSoldier = {
  [K in keyof Soldier]?: Soldier[K];
};

What if instead of making all the properties optional, we instead wanted to filter any non-string properties? We can do that with a conditional mapped type:

type FilteredSoldier = {
  [K in keyof Soldier]: Soldier[K] extends string ? Soldier[K] : never;
};

The conditional: Soldier[K] extends string only evaluates to true (and thus the property is included as Soldier[K]) if the property is assignable to string. Otherwise, it evaluates to never, and the property is excluded. One really cool thing to note, is that because we used Soldier[K] in the conditional, the more specific type of the branch property is preserved, resulting in a type of:

type FilteredSoldier = {
  name: string;
  // age: never;
  branch: "garrison" | "military police" | "survey corps";
};

Assignment

The compliance team at Support.ai is reviewing what user-visible data can be edited, and what should be locked.

Tip

Use T[K] extends Function | object to check each field.