Open In App

TypeScript Conditional Types

Last Updated : 24 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

In this article, we are going to discuss Conditional Types. Conditional types in TypeScript are a powerful feature that allows you to create types that depend on a condition or a set of conditions. As JavaScript is a loosely typed language, conditional types enable you to define types that are based on the values or the properties of other types. It uses the extend keyword and a to define a condition and then produce different types based on whether that condition is true or false. This takes a form that looks a little like conditional expressions (condition ? trueExpression: false expressions.

Syntax

type ConditionalType<T> = T extends Condition ? value 1: value 2;

Where-

  • ConditionalType<T> is the name of the type having <T> type parameter.
  • T extends Condition is the condition that will return true or false
  • Value1 is the value when the condition will be true.

Example: In this example, We define a conditional type Num<T> that checks whether the given type T is an array of numbers, an array of strings, or neither, and returns either number, string, or never accordingly. It then uses this conditional type to declare variables num and ‘stringnum’ with specific type assignments, resulting in type-checking errors because the assignments do not match the expected types, and finally logs the variables.

 

Javascript




type Num<T> = T extends number[] ? number 
    : (T extends string[] ? string : never)
      
// Return num
const num: Num<number[]> = 4;
  
// Return invalid
const stringnum: Num<number> = "7";
  
console.log(num, stringnum);


Output:ConditionlaTS

Conditional Type Constraints

Conditional Types Constraints also called as Conditional Types Predicates or Type Assertion are a TypeScript feature that allows you to define constraints on generic types within conditional types. They provide a way to narrow down the possible types a generic can be based on a condition. This is particularly useful when you want to perform type checks or assertions within a conditional type.

Syntax

type ConditionalType<T> = T extends OtherConditionalType ? Value 1 : Value 2;

Example: In this example We defines a type CheckNum<T> that checks whether a type T is a number or not. It returns T if it’s a number and never otherwise. Then, it defines another type NumbersOnly<T> which is a mapped type that operates on arrays. It iterates over the keys of the input array type T and uses CheckNum to filter out non-number elements from the array.

Javascript




type CheckNum<T> = T extends number ? T : never;
  
type NumbersOnly<T extends any[]> = {
    [K in keyof T]: CheckNum<T[K]>;
};
  
// Return num
const num: NumbersOnly<[4, 5, 6, 8]> = [4, 5, 6, 8];
  
// Return invalid
const stringnum: NumbersOnly<[4, 6, "7"]> = [4, 6, "7"];


Output:

ConstraintTS

Inferring Within Conditional Types:

Inferring within conditional types in TypeScript is a technique that allows you to infer types within a conditional type definition. It’s a powerful way to create more precise and flexible type transformations. TypeScript introduced this capability in version 4.1, enhancing the expressiveness of conditional types.

Syntax

type ConditionalType<T> = T extends Condition ? (infer U) => void : Value 2;

Where-

  • infer is a keyword which is used to create a new generic type variable named U
  • Value2 will be the output whenever the condition is false.

Example: This examples we define a conditional type ConvertToStringOrNumber that transforms types based on a condition. We use this type within a function convertValue to dynamically convert input values to either strings or numbers based on their types. The examples showcase how the function’s conditional logic produces different runtime outputs when applied to strings and numbers.

Javascript




type ElementType<T> = T extends (infer U)[] ? U : never;
  
const numbers: number[] = [1, 2, 3, 4, 5];
const strnumber: String[] = ["1", "3", "7"];
const element: ElementType<typeof numbers> = numbers[0];
  
// This is invalid it will give error
const element2: ElementType<typeof numbers> = strnumber[0];
  
// Output: 1
console.log(element);


Output:

Screenshot-2023-09-22-214105

Distributive Conditional Types

Distributive conditional types in TypeScript are a feature that allows a conditional type to automatically distribute over a union of types. This means that when you apply a distributive conditional type to a union of types, TypeScript will independently evaluate the conditional type for each member of the union and produce a union of the results.

Syntax:

type DistributiveConditional<T | T | T> = T extends Condition ? Value 1 : Value 2;

Where-

  • <T | T | T> is the different type of types.
  • Value1 will be given as a output whenever the condition will be true.
  • Value2 will be given as a output whenever the condition will be false.

Example: In this example we will create a ColorMapping type that will map the numbers based on the value of ColorClassMap such as red, green, blue and then create a function that will takes value and infer them with type.

Javascript




type Colors = 'red' | 'blue' | 'green';
  
// Define a mapping from color to CSS class
type ColorClassMap = {
    'red': 'danger',
    'blue': 'primary',
    'green': 'success',
};
  
// Distributive conditional type to map 
// colors to CSS classes
type MapColorsToClasses<T extends string> 
    = T extends keyof ColorClassMap
    ? { [K in T]: ColorClassMap[T] }
    : never;
  
// Apply the distributive
// type to the Colors union
type ColorClasses = MapColorsToClasses<Colors>;
  
const redClass: ColorClasses = {
    red: 'danger',
};
  
const blueClass: ColorClasses = {
    blue: 'primary',
};
  
const greenClass: ColorClasses = {
    green: 'success',
};
  
// This would result in a type error 
// since 'yellow' is not in the Colors union
// const yellowClass: ColorClasses = {
//   yellow: 'warning',
// };
console.log(redClass, blueClass, greenClass)


Output:

DistributiveTS

Conclusion: In this article, we have seen what is ConditionalType and its syntax. It is used to define types based on condition. Then we saw Constional Type Constraints, Infering Withing Conditional Type and Distributive Conditional Type By using the Conditional Type<Type> type, you can define the type based on certain condition.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads