typescript - parametrar där den ena är enum och den andra är en union av strängar som är giltiga nycklar för detta enum


Jag skriver en ganska enkel sorteringsfunktion för backend-API. Om det inte finns någon sortering returnerar den en tom sträng. Om det finns sortering returnerar den ett värde taget från ett enum baserat på kolumn + några mindre modifieringar. Men jag har problem med typer. sort, när den inte är null, har en sortBy som är T som skickas till denna funktion (union av strängar), detta fungerar okej. Jag vet inte hur jag ska skicka Enum till funktionen där sort.sortBy är en giltig nyckel i det enumet.

type SortState = null | {sortBy: string; sortAsc: boolean; }

const handleSort = <T, K extends T>(sort: SortState, sortEnum: K) => {
      if (!sort) {
        return '';
      }
      const name = sort.sortBy as T;
      const order = sort.sortAsc;
      const newQuery = `${order ? '-' : ''}${order ? sortEnum[name].replaceAll(',', ',-') : sortEnum[name]}`;

      return newQuery;
 };

enum SortEnum {
  bar = 'bar',
  foo = 'foo'
}

type TableHeaders = 'foo' | 'bar'

const sortQuery = handleSort<TableHeaders>({sortBy: 'bar', sortAsc: false}, SortEnum)

Svar #1

Med tanke på din implementation och anrop skulle jag vara benägen att göra handleSort() generisk i typen K som motsvarar sortBy-egenskapen av sort-argumentet, vilket också är en nyckel i sortEnum-argumentet. På detta sätt:

const handleSort = <K extends PropertyKey>(
    sort: null | { sortBy: K, sortAsc: boolean },
    sortEnum: Record<K, string>
) => {
    if (!sort) {
        return '';
    }
    const name = sort.sortBy;
    const order = sort.sortAsc;
    const newQuery = `${order ? '-' : ''}${
          order ? sortEnum[name].replaceAll(',', ',-') : sortEnum[name]
        }`;
    return newQuery;
};

Parametern sortEnum är av typen Record<K, string> som använder Record-hjälptypen för att betyda "en typ med en string-värd egenskap på varje nyckel av typen K". Implementeringen typkontrolleras eftersom kompilatorn förstår att name är av typen K (om sort är sant) och därmed att sortEnum[name] är av typen string.

Låt oss testa samtalssidan:

const sortQuery = handleSort(
    { sortBy: 'bar', sortAsc: false },
    SortEnum
); // okay

const sortQuery2 = handleSort(
    { sortBy: 'baz', sortAsc: false },
    SortEnum // error!
//  ~~~~~~~~ <-- Property 'baz' is missing in type 'typeof SortEnum'
);

Ser bra ut. Kompilatorn är nöjd när sortBy matchar en nyckel i SortEnum, och missnöjd när den inte gör det.

Lekplatslänk till kod