如何为健康属性合并逻辑中reduce函数的v指定有意义的TS类型?
any with a Precise Type in Your Health Attribute Merge Logic Great question! Using any defeats the purpose of TypeScript's type safety, so let's fix that by defining clear, specific types for your code. Here's how to do it step by step:
Step 1: Confirm Your Base Types
First, make sure you have explicit type definitions for the core entities in your code. Based on your snippet, these should look something like this (adjust to match your actual schema):
// Define your ID type (adjust if you use numbers or another format) type RecordId = string; // Define the structure of a HealthAttribute based on your code usage interface HealthAttribute { relationships: { health_attribute_definition: { data: { id: RecordId; }; }; }; attributes: { created_at: string; // Or Date if you parse dates upfront // Add other attribute fields here }; // Add any top-level fields for HealthAttribute here } // Define the Request/Renewal type (matches request_or_renewal in your code) interface RequestOrRenewal { attributes: { created_at: string; // Or Date // Add other request/renewal fields here }; // Add any top-level fields here }
Step 2: Type the First Reduce Result
Update your first reduce to explicitly type the accumulated object, so TypeScript knows what sorted_attributes_by_definition_id contains:
// Explicitly type the accumulator as Record<RecordId, HealthAttribute[]> const sorted_attributes_by_definition_id: Record<RecordId, HealthAttribute[]> = sorted_health_attributes_to_merge.reduce((acc, attr) => { const had_id = attr.relationships.health_attribute_definition.data.id; if (!acc[had_id]) { // eslint-disable-next-line nurx/no-param-reassign acc[had_id] = []; } acc[had_id].push(attr); return acc; }, {} as Record<RecordId, HealthAttribute[]>); // Use type assertion to initialize empty object
Step 3: Replace any with HealthAttribute[] in the Second Reduce
Now that sorted_attributes_by_definition_id has a clear type, _.toPairs() will return an array of [RecordId, HealthAttribute[]] pairs. You can directly replace any with HealthAttribute[] for v:
// Type the merged result explicitly too for extra safety const merged_health_attributes: Record<RecordId, { recent: HealthAttribute | null; prev: HealthAttribute[] }[]> = _.toPairs(sorted_attributes_by_definition_id).reduce((acc, [had_id, v]: [RecordId, HealthAttribute[]]) => { let recent: HealthAttribute | null = null; let prev: HealthAttribute[] = []; if (v[0]) { const recent_created_at = moment(v[0].attributes.created_at); const source_created_at = moment(request_or_renewal.attributes.created_at); if (source_created_at.diff(recent_created_at, 'days') > 1) { prev = v; } else { recent = v[0]; prev = v.slice(1); } } const to_push = { recent, prev }; if (!acc[had_id]) { // eslint-disable-next-line nurx/no-param-reassign acc[had_id] = []; } acc[had_id].push(to_push); return acc; }, {} as Record<RecordId, { recent: HealthAttribute | null; prev: HealthAttribute[] }[]>);
Why This Works
vis now typed asHealthAttribute[]because we groupedsorted_health_attributes_to_merge(aHealthAttribute[]) byhad_id—each value in the grouped object is an array of matching health attributes.- TypeScript will now catch errors like accessing non-existent properties on
vor its elements, and give you helpful autocomplete.
内容的提问来源于stack exchange,提问作者Malik Kamran Abid

