A conditional type chooses a result type from a relationship involving a generic type parameter. Its `extends` test resembles a ternary expression, but the choice is made by the TypeScript compiler, not by JavaScript at runtime. section 13.6
Choose a type from a boolean type argument
In `src/index.ts`: ```ts type resultType<T extends boolean> = T extends true ? string : number; let firstVal: resultType<true> = "String Value"; let secondVal: resultType<false> = 100; let mismatchCheck: resultType<false> = "String Value"; // error ``` The last declaration fails because `resultType<false>` resolves to `number`. The `boolean` constraint limits which type arguments the alias accepts. section 13.6
A conditional type can also connect an input choice to a method’s result. For a `Collection<T>.total` method, a `true` formatting argument selects a `string` result; `false` selects `number`. The compiler can infer the relevant type argument from that value. This is more concise than function overloads, though it can be harder to read. section 13.6.2
Listing 13.25 Defining a generic type in the index.ts file in the src folder
import { City, Person, Product, Employee } from "./dataTypes.js";
type resultType<T extends boolean> = T extends true ? string : number;
class Collection<T> {
private items: T[];
constructor(...initialItems: T[]) {
this.items = initialItems || [];
}
total<P extends keyof T, U extends boolean>(propName: P, format: U)
: resultType<U> {
let totalValue = this.items.reduce((t, item) =>
t += Number(item[propName]), 0);
return format ? `$${totalValue.toFixed()}` : totalValue as any;
}
}
let data = new Collection<Product>(new Product("Kayak", 275),
new Product("Lifejacket", 48.95));
let firstVal: string = data.total("price", true);
console.log(`Formatted value: ${firstVal}`);
let secondVal: number = data.total("price", false);
console.log(`Unformatted value: ${secondVal}`);
The complete `src/index.ts` listing shows the conditional return type beside the method implementation and calls that assign its results to `string` and `number` variables. section 13.6.2
There is a practical limit: the compiler may not correlate return values inside a method with its conditional return type. The `total` implementation uses an `any` assertion to get past that difficulty. Check both branches yourself; the assertion does not make an incorrect return value safe. section 13.6.2 section 13.6
Transform selected properties
A conditional type inside a mapped type can change only properties whose types match a target: ```ts type changeProps<T, U, V> = { [P in keyof T]: T[P] extends U ? V : T[P] }; type modifiedProduct = changeProps<Product, number, string>; ``` For a `Product` with `name` and numeric `price`, `modifiedProduct` has string types for both properties. A conversion function supplies the formatted price value; the type transformation does not perform that conversion. section 13.6.4
Accept only property names of a given type
To constrain a numeric-total function’s property name, map each matching property to its own name and each other property to `never`: ```ts type unionOfTypeNames<T, U> = { [P in keyof T]: T[P] extends U ? P : never; }; type propertiesOfType<T, U> = unionOfTypeNames<T, U>[keyof T]; ``` For `Product` and `number`, indexed access yields `"price"` after `never` is removed from the union. That union can constrain the function’s property-name parameter. section 13.6.5
The `infer` keyword handles types that must be discovered within a condition. For example, `T extends (infer U)[] ? keyof U : keyof T` selects an array element’s keys when `T` is an array, rather than the array’s own keys. It can also extract a function’s result type; built-in conditional types include `ReturnType<T>` and `InstanceType<T>`. section 13.6.6
Use conditional types when simpler generic types cannot express the required relationship. As conditions grow, review their possible type combinations: an overly broad result can leave a type-checking hole, while an overly narrow one rejects valid uses. The types themselves are removed during compilation. section 13.6 section 13.7
