skip to Main Content

I want to sort an array of objects by either a string or a number. If it is a string, I want to call .toLowerCase() on it first. I’m making that distinction using typeof in the condition of a ternary statement.

interface ObjectProps {
    sortFoo: string,
    sortBar: number
}

const sortBy: "sortFoo" | "sortBar" = getSortKey();

const sortList = (...args: ObjectProps[]): number => {
    const compare: (string | number)[] = args.map(
        (arg: ObjectProps): string | number => typeof arg[sortBy] === 'string' ? arg[sortBy].toLowerCase() : arg[sortBy]
    );

    return compare[0] < compare[1] ? -1 : 1;
}

const objects: ObjectProps[] = getArrayOfObjects().sort(sortList);

This code will run just fine, but TS flags .toLowerCase() with this error:

TS2339: Property  toLowerCase  does not exist on type  string | number 
Property  toLowerCase  does not exist on type  number

How do I tell the TS engine that if typeof myVar === 'string' evaluates as false, then myVar is not a string?

I tried replacing the ternary with a full if clause, as in this tutorial (scroll down to the section titled "Unknown"), but TS still showed the same error. Not sure what else to try.

2

Answers


  1. Looks like Typescript only performs that type narrowing on a variable, not necessarily a property that you’re accessing. So you just need to store the property in a variable first, something like this:

    const sortList = (...args: ObjectProps[]): number => {
        const compare: (string | number)[] = args.map(
            (arg: ObjectProps): string | number => {
              const sortVal = arg[sortBy];
              return typeof sortVal === 'string' ? sortVal.toLowerCase() : sortVal;
            }
        );
    
        return compare[0] < compare[1] ? -1 : 1;
    }
    
    Login or Signup to reply.
  2. try this hopefully this will help you

    const sortList = (...args: ObjectProps[]): number => {
    const compare: (string | number)[] = args.map(
        (arg: ObjectProps): string | number => {
            if (typeof arg[sortBy] === 'string') {
                //--> arg[sortBy] is a string
                return (arg[sortBy] as string).toLowerCase();
            } else {
                //--> arg[sortBy] is not a string
                return arg[sortBy];
            }
        }
    );
    
      return compare[0] < compare[1] ? -1 : 1;
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search