TypeScript中如何将类型泛型扩展至函数?能否实现无复制粘贴的泛型复用?
Great question! Duplicating generic constraints is a common annoyance in TypeScript, but there are clean ways to reuse them without copying code. Let’s walk through two reliable approaches for your scenario.
Approach 1: Extract Constraints & Defaults into Shared Types
The most straightforward method is to pull the generic constraints and default values into separate top-level type aliases. This lets both your T type and func function reference the same definitions—so you only ever need to update them in one place:
// Step 1: Define shared constraints and defaults once type TFormTypeConstraint = 'edit' | 'create'; type TRecordTypeConstraint = Record; type TFormTypeDefault = 'create'; type TRecordTypeDefault = Record; // Step 2: Reuse them in your type T type T< FormType extends TFormTypeConstraint = TFormTypeDefault, RecordType extends TRecordTypeConstraint = TRecordTypeDefault > = { type: FormType, record: RecordType }; // Step 3: Reuse the same constraints/defaults in your function const func = < FormType extends TFormTypeConstraint = TFormTypeDefault, RecordType extends TRecordTypeConstraint = TRecordTypeDefault >(props: T<FormType, RecordType>) => { // Your function logic here };
This approach is highly readable and scales well if you need to reuse these constraints across other parts of your codebase.
Approach 2: Extract Generic Params from Type T Using infer
If you prefer to keep everything tightly coupled to your original T type, you can use TypeScript’s infer keyword to extract its generic constraints and defaults directly:
// Keep your original type T definition type T<FormType extends 'edit' | 'create' = 'create', RecordType extends Record = Record> = { type: FormType, record: RecordType }; // Create a utility type to pull T's generic details type ExtractTGenerics = T extends T<infer F, infer R> ? { FormType: F extends 'edit' | 'create' ? F : never; RecordType: R extends Record ? R : never; DefaultFormType: 'create'; DefaultRecordType: Record; } : never; // Reuse the extracted details in your function const func = < FormType extends ExtractTGenerics['FormType'] = ExtractTGenerics['DefaultFormType'], RecordType extends ExtractTGenerics['RecordType'] = ExtractTGenerics['DefaultRecordType'] >(props: T<FormType, RecordType>) => { // Your function logic here };
With this method, any updates to T’s constraints or defaults will automatically propagate to the function—no manual changes needed.
Can We Achieve Generic Reuse Without Copy-Pasting?
Absolutely! Both approaches above eliminate duplicate code entirely. The first is better for maintainability when constraints might be reused across multiple types/functions, while the second is ideal if you want all definitions tied directly to T.
内容的提问来源于stack exchange,提问作者Oki

