Home > Back-end >  return type of map array in typescript
return type of map array in typescript

Time:11-24

I have this function

export const handleSortableColumns = (headerKeys: string[], sortKeys: object): string[] => {
  if (!headerKeys) return [];

  return headerKeys.map((key: string): any => sortKeys[key] || null);
};

so headerKeys parameter takes list of string sortKeys parameter should take an object but I think it's wrong to put object type and I can't define type or interface because each time it will be different properties. should I specify generic type ? how I can do that ? also the return type will be a list of strings that contains null values as well so what should be return type using any type is forbidden

CodePudding user response:

For the sortKeys you could do it like this

interface ISortKeys {
  [key: string]: string
}

For the return type you could use

(string|null)[]

CodePudding user response:

I switched sortKeys and headerKeys. This helps usability because the type checker immediately knows on what object you're operating on. I also made headerKeys variadic but you can revert it back to a regular array, if you prefer that.

const handleSortableColumns = <T>(sortKeys: T, ...headerKeys: (keyof T & string)[]): (string | null)[] => {
    if (!headerKeys) return [];
    const result = headerKeys.map(key => sortKeys[key] || null);
    return result as (string | null)[];
}

.

handleSortableColumns({ a: '1', b: 2 }, 'a', 'X');

Is now a type error. But this doesn't save you from

handleSortableColumns({ a: '1', b: 2 }, 'a', 'b');

Including more strict return type checks quickly turns into an unreadable type soup. I'd recommend using run time checks, filter or throw, instead.

CodePudding user response:

You can use generic type parameters to infer the types of the input values, and then use those generics to create an array return type which represents the subset of values in the object that can be indexed by the values in the input array (or null). Here's an example:

TS Playground

function handleSortableColumns <
  Keys extends readonly string[],
  ValueMap extends Record<string, unknown>,
>(headerKeys: Keys, valueMap: ValueMap): (ValueMap[Extract<keyof ValueMap, Keys[number]>] | null)[] {
  return headerKeys.map(
    key => (valueMap[key] ?? null) as ValueMap[Extract<keyof ValueMap, Keys[number]>] | null
  );
}

const keys = ['a', 'b', 'c'] as const;

const map = {
  a: 1,
  c: false,
  d: 'hello world',
};

const result = handleSortableColumns(keys, map);
    //^? const result: (number | boolean | null)[]

console.log(result); // [1, null, false]

Compiled JS from the TS Playground:

"use strict";
function handleSortableColumns(headerKeys, valueMap) {
    return headerKeys.map(key => (valueMap[key] ?? null));
}
const keys = ['a', 'b', 'c'];
const map = {
    a: 1,
    c: false,
    d: 'hello world',
};
const result = handleSortableColumns(keys, map);
//^?
console.log(result); // [1, null, false]

  • Related