Intel停办IDF大会:将改变策略不再严重依赖PC
TypeScript's advanced condition types implement logical judgment between types through the T extends U? X: Y syntax. Its core capabilities are reflected in the distributed condition types, infer type inference and the construction of complex type tools. 1. The conditional type is distributed in the bare type parameters and can automatically split the joint type, such as ToArray
Advanced Conditional Types of TypeScript are one of the most powerful and flexible parts of the type system. They allow you to dynamically generate new types based on relationships between types, and are often used to build complex type tools, type guards, and generic abstractions. Understanding these features will allow you to write safer and smarter type code.

Here are some key concepts and practical tips that will take you into the deep understanding of advanced condition types.
1. Syntax and basic principles of conditional types
The syntax of conditional types is similar to that of JavaScript's ternary operators:

T extends U ? X : Y
Meaning: If type T
can be assigned to U
, then the result type is X
, otherwise it is Y
example:

type IsString<T> = T extends string ? true : false; type A = IsString<'hello'>; // true type B = IsString<42>; // false
This seems simple, but its true power is reflected in combination with generics, union types, and distributed conditional types.
2. Distributed Conditional Types
When the conditional type acts on a generic and the generic appears to the left extends
, TypeScript will automatically "distribute" the union type.
type ToArray<T> = T extends any ? T[] : never;
If you pass string | number
, TypeScript will disassemble it:
ToArray<string | number> // Equivalent to: // (string extends any ? string[] : never) | (number extends any ? number[] : never) // The result is: string[] | number[]
? This "automatic distribution" only occurs on naked type parameters. If you wrap
T
in a tuple or object, such as[T] extends [any]
, the distribution will be closed.
Purpose: Commonly used to process each item in a joint type separately, such as the extraction/filter type.
3. Type filtering and extraction tools
With distributed conditional types, we can build powerful type tools.
Extract function type
type GetFunction<T> = T extends (...args: any[]) => any ? T : never; type FuncsOnly = GetFunction<string | () => number | number | (s: string) => void>; // Result: () => number | (s: string) => void
Exclude certain types (similar to Exclude
)
type Exclude<T, U> = T extends U ? never : T; type NoString = Exclude<string | number | boolean, string>; // number | boolean
This is how TypeScript's built-in Exclude<T, U>
is implemented.
Extract certain types (similar to Extract
)
type Extract<T, U> = T extends U ? T : never; type OnlyStringOrNumber = Extract<string | number | boolean, string | number>; // string | number
Filter null/undefined (similar to NonNullable
)
type NonNullable<T> = T extends null | undefined ? never : T; type A = NonNullable<string | null | undefined>; // string
4. infer
: Infer type in conditional type
infer
is a weapon for "pattern matching" and extracting subtypes in conditional types.
Extract function return value type (similar to ReturnType
)
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never; type R = ReturnType<() => string>; // string
Extract array element type (similar to ElementType
)
type ElementType<T> = T extends (infer U)[] ? U : never; type Item = ElementType<number[]>; // number type Item2 = ElementType<string[]>; // string
Extract the parsed value of the Promise (similar to Awaited
)
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T; type Value = UnwrapPromise<Promise<string>>; // string type Value2 = UnwrapPromise<number>; // number
infer
can appear in tuples, function parameters, return values, object properties, etc., to realize complex type deconstruction.
5. Practical Advanced Mode
1. DeepReadonly
type DeepReadonly<T> = { readonly [K in keyof T]: T[K] extends object ? T[K] extends Function ? T[K] : DeepReadonly<T[K]> : T[K]; };
Here we use the condition type to determine whether the field is an object and avoid recursion of the function.
2. Function overload parsing (simplified signature)
type FirstParam<F> = F extends (arg: infer P) => any ? P : never; type ID = FirstParam<(id: string) => void>; // string
3. Joint transfer cross type (advanced skills)
Sometimes you want to convert string | number
to string & number
(although the result is never
), but it is more common to use "inverter" processing for function parameters.
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never; type T = UnionToIntersection<{a:1} | {b:2}>; // {a:1} & {b:2}
This technique is often used to "merge" multiple types in type derivation.
6. Common traps and precautions
never will be ignored in union type
type T = string | never; // equivalent to string
Therefore, it is effective to use
never
to "filter out" the type inExclude
.Condition types are lazy
Conditional types are calculated only when instantiated. For example:
type Foo<T> = T extends string ? string : number; type A = Foo<any>; // type is string | number
Because
any
andstring
are "fuzzy", TypeScript will conservatively returnstring | number
.Never's special behavior
never
is a subtype of all types, so in the conditional type:type T = never extends string ? true : false; // true
But this does not mean that
never
is a string, but that is the type system rules.
Summarize
Advanced conditional types are at the heart of TypeScript type programming. Combining
extends
,infer
and distributed behavior, you can:- Filter, extract, convert types
- Implement type-level "logical judgment"
- Build complex generic tools (such as
Pick
,Omit
,ReturnType
, etc.)
Although it seems like magic at the beginning, as long as you understand the idea of "type is a set" and "conditional type is a set judgment", you can gradually master it.
Basically that's it. Write more and try more, and you will find that the type system is more powerful than you think.
The above is the detailed content of Advanced Conditional Types in TypeScript. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

The settings.json file is located in the user-level or workspace-level path and is used to customize VSCode settings. 1. User-level path: Windows is C:\Users\\AppData\Roaming\Code\User\settings.json, macOS is /Users//Library/ApplicationSupport/Code/User/settings.json, Linux is /home//.config/Code/User/settings.json; 2. Workspace-level path: .vscode/settings in the project root directory

itertools.combinations is used to generate all non-repetitive combinations (order irrelevant) that selects a specified number of elements from the iterable object. Its usage includes: 1. Select 2 element combinations from the list, such as ('A','B'), ('A','C'), etc., to avoid repeated order; 2. Take 3 character combinations of strings, such as "abc" and "abd", which are suitable for subsequence generation; 3. Find the combinations where the sum of two numbers is equal to the target value, such as 1 5=6, simplify the double loop logic; the difference between combinations and arrangement lies in whether the order is important, combinations regard AB and BA as the same, while permutations are regarded as different;

To correctly handle JDBC transactions, you must first turn off the automatic commit mode, then perform multiple operations, and finally commit or rollback according to the results; 1. Call conn.setAutoCommit(false) to start the transaction; 2. Execute multiple SQL operations, such as INSERT and UPDATE; 3. Call conn.commit() if all operations are successful, and call conn.rollback() if an exception occurs to ensure data consistency; at the same time, try-with-resources should be used to manage resources, properly handle exceptions and close connections to avoid connection leakage; in addition, it is recommended to use connection pools and set save points to achieve partial rollback, and keep transactions as short as possible to improve performance.

DependencyInjection(DI)isadesignpatternwhereobjectsreceivedependenciesexternally,promotingloosecouplingandeasiertestingthroughconstructor,setter,orfieldinjection.2.SpringFrameworkusesannotationslike@Component,@Service,and@AutowiredwithJava-basedconfi

fixture is a function used to provide preset environment or data for tests. 1. Use the @pytest.fixture decorator to define fixture; 2. Inject fixture in parameter form in the test function; 3. Execute setup before yield, and then teardown; 4. Control scope through scope parameters, such as function, module, etc.; 5. Place the shared fixture in conftest.py to achieve cross-file sharing, thereby improving the maintainability and reusability of tests.

Python is an efficient tool to implement ETL processes. 1. Data extraction: Data can be extracted from databases, APIs, files and other sources through pandas, sqlalchemy, requests and other libraries; 2. Data conversion: Use pandas for cleaning, type conversion, association, aggregation and other operations to ensure data quality and optimize performance; 3. Data loading: Use pandas' to_sql method or cloud platform SDK to write data to the target system, pay attention to writing methods and batch processing; 4. Tool recommendations: Airflow, Dagster, Prefect are used for process scheduling and management, combining log alarms and virtual environments to improve stability and maintainability.

java.lang.OutOfMemoryError: Javaheapspace indicates insufficient heap memory, and needs to check the processing of large objects, memory leaks and heap settings, and locate and optimize the code through the heap dump analysis tool; 2. Metaspace errors are common in dynamic class generation or hot deployment due to excessive class metadata, and MaxMetaspaceSize should be restricted and class loading should be optimized; 3. Unabletocreatenewnativethread due to exhausting system thread resources, it is necessary to check the number of threads, use thread pools, and adjust the stack size; 4. GCoverheadlimitexceeded means that GC is frequent but has less recycling, and GC logs should be analyzed and optimized.

Use classes in the java.time package to replace the old Date and Calendar classes; 2. Get the current date and time through LocalDate, LocalDateTime and LocalTime; 3. Create a specific date and time using the of() method; 4. Use the plus/minus method to immutably increase and decrease the time; 5. Use ZonedDateTime and ZoneId to process the time zone; 6. Format and parse date strings through DateTimeFormatter; 7. Use Instant to be compatible with the old date types when necessary; date processing in modern Java should give priority to using java.timeAPI, which provides clear, immutable and linear
