Home > front end >  Why Keyof makes object undefined and impossible to make a proper check
Why Keyof makes object undefined and impossible to make a proper check

Time:07-06

I have TS2532: Object is possibly 'undefined' when I try to find an object's value by dynamically selecting the key. For some reason, typescript doesn't allow me to check the values of the field and I'm not sure what the reason is. Check the code below, please!

import {calculateAge} from "../helpers/ageCalculator";

export class EmployeeModel {
    id: number;
    first_name: string;
    last_name: string;
    birthdate: string;
    email: string;
    gender: string;
    department: string;
    age?: number = 0;

    constructor(employee: EmployeeModel = {} as EmployeeModel) {
        this.id = employee.id;
        this.first_name = employee.first_name;
        this.last_name = employee.last_name;
        this.birthdate = employee.birthdate;
        this.email = employee.email;
        this.gender = employee.gender;
        this.department = employee.department;
        this.age = calculateAge(employee.birthdate);
    }
    export const useGetEmployees = () => {
    const [searchParams] = useSearchParams();

    const sortBy = searchParams.get('sortBy');
    const direction = searchParams.get('direction');

    const compareFunc = (a:EmployeeModel, b: EmployeeModel) => {
        let sortResult = 0;

        if (a === undefined && b === undefined) {
            return 0;
        }

        //TS2532: Object is possibly 'undefined'.
        if (a[sortBy as keyof EmployeeModel] < b[sortBy as keyof EmployeeModel]){
            sortResult = -1;
        }

        //TS2532: Object is possibly 'undefined'.
        if ( a[sortBy as keyof EmployeeModel] > b[sortBy as keyof EmployeeModel] ){
            sortResult = 1;
        }

        else return sortResult;
        return  direction === SortDirection.Desc ? -sortResult : sortResult;
    };

    const { data, isLoading, status } = useQuery('employeeList', getEmployeeList, {
        select: (employees: EmployeeModel[]) => employees.map(
            (employee: EmployeeModel) => {
                return new EmployeeModel(employee);
            }
        ).sort(compareFunc),
    });
    return {employees: data, isLoading, status} as const;
}
export const calculateAge = (birthdate: string) : number => {
    const currentDate = new Date();
    const currentYear = currentDate.getFullYear();

    const birthDate = new Date(birthdate);
    const birthYear = birthDate.getFullYear();

    return currentYear - birthYear;
}

UPD: Added calculateAge() code

CodePudding user response:

Your main problem comes from age?. It could be undefined and as such any access to a EmployeeModel via a key string could be undefined.

You have a few options here:

  1. define age as number: age: number, but I don't know how calculateAge looks like.
  2. get the values from a[key] and b[key] and check them for undefined.
  3. exclude age from the list of keys.
const key: Exclude<keyof EmployeeModel, "age"> = sortBy as Exclude<keyof EmployeeModel, "age">
    
if (key) {
   if (a[key] < b[key]){
      sortResult = -1;
   }

   if ( a[key] > b[key] ){
       sortResult = 1;
   }
}   

A few notes:

  • this check if (a === undefined && b === undefined) is not needed.
  • I would create a key value at the top and reuse it. Something like this
        const key: = sortBy as keyof EmployeeModel
    
        if (key) {
            if (a[key] < b[key]){
                sortResult = -1;
            }

            if ( a[key] > b[key] ){
                sortResult = 1;
            }
        }  
  • Related