TypeScript中避免多if检查属性为空及查询参数代码优化
Great question! Dealing with those repetitive if checks when building query params is such a common pain point—let's look at a few cleaner, more maintainable approaches for your TypeScript code.
Approach 1: Use a Mapping Array for Centralized Logic
This method lets you define all your field-to-param mappings in one place, so you don't have to write a separate if for every property. It's especially useful if you expect to add more filters later.
private buildQueryParams(filterData: BaseFilterModel | RegistrationFilterModel): HttpParams { let params = new HttpParams(); if (!filterData) return params; // Define how each filter field maps to a query param, including transformations const paramMappings = [ { paramKey: 'regionId', getValue: (data: typeof filterData) => data.regionId, transform: (value: number) => value.toString() }, { paramKey: 'facilityId', getValue: (data) => data.facilityId, transform: (value: number) => value.toString() }, { paramKey: 'dept1', getValue: (data) => data.dept1?.id, // Use optional chaining to safely access nested properties transform: (value: number) => value.toString() } // Add more mappings here as needed ]; // Loop through mappings and add non-null/undefined values to params for (const mapping of paramMappings) { const value = mapping.getValue(filterData); if (value != null) { // Exclude null and undefined params = params.set(mapping.paramKey, mapping.transform(value)); } } return params; }
Why this works:
- No more repetitive
ifblocks—all logic lives in the mapping array - TypeScript's optional chaining (
?.) eliminates nestedifchecks for properties likedept1.id - Easy to extend: just add a new object to the
paramMappingsarray when you need a new filter
Approach 2: Build a Raw Object First (Simpler for Smaller Sets)
If you only have a handful of fields to handle, you can first construct a plain object with valid values, then initialize HttpParams all at once using the fromObject option.
private buildQueryParams(filterData: BaseFilterModel | RegistrationFilterModel): HttpParams { if (!filterData) return new HttpParams(); const validParams: Record<string, string> = {}; // Add valid fields to the object if (filterData.regionId != null) validParams.regionId = filterData.regionId.toString(); if (filterData.facilityId != null) validParams.facilityId = filterData.facilityId.toString(); if (filterData.dept1?.id != null) validParams.dept1 = filterData.dept1.id.toString(); // Initialize HttpParams in one go return new HttpParams({ fromObject: validParams }); }
Why this works:
- Reduces repeated calls to
params.set() - Keeps your logic concise for smaller filter sets
- Still leverages optional chaining to avoid nested
ifchecks
Approach 3: Reusable Utility Function (For Cross-Project Use)
If you find yourself building query params in multiple places, wrap the logic in a reusable utility function to avoid duplication.
// Utility function to filter and transform filter data into a query object function transformToQueryParams<T>( filterData: T, mappings: Array<{ paramKey: string; getValue: (data: T) => any }> ): Record<string, string> { return mappings.reduce((acc, mapping) => { const value = mapping.getValue(filterData); if (value != null) { acc[mapping.paramKey] = String(value); } return acc; }, {} as Record<string, string>); } // Use the utility in your component/service private buildQueryParams(filterData: BaseFilterModel | RegistrationFilterModel): HttpParams { if (!filterData) return new HttpParams(); const queryObject = transformToQueryParams(filterData, [ { paramKey: 'regionId', getValue: d => d.regionId }, { paramKey: 'facilityId', getValue: d => d.facilityId }, { paramKey: 'dept1', getValue: d => d.dept1?.id } ]); return new HttpParams({ fromObject: queryObject }); }
Why this works:
- Encapsulates repeated logic in one place
- Makes it easy to standardize query param handling across your app
- Keeps your component/service code clean and focused
All these approaches eliminate messy nested if statements while keeping your type safety intact. Choose the one that fits your project's size and reuse needs—for quick one-off cases, Approach 2 is ideal; for larger or scalable scenarios, Approach 1 or 3 will save you time long-term.
内容的提问来源于stack exchange,提问作者Khakis7

