WblCHA
@WblCHA

Как заставить TS работать с группами типов?

Есть функция:
const f = (someObj: T1 | T2, someEnum: typeof E1 | typeof E2): string => {
    return someObj[someEnum.a];
};

Она должна принимать на вход либо T1 + E1, либо T2 + E2.
Сltлать такое ограничение не проблема и оно сделано (код ниже), НО в strict моде someObj[someEnum.a] вылезает ошибка (ts(7053)) во всех вариантах, что я опробовал (в частности, оверлоадинг и аргументы в виде объекта).

Ошибка:
Element implicitly has an 'any' type because expression of type 'E1.a | E2.a' can't be used to index type 'T1 | T2'.
  Property '[E1.a]' does not exist on type 'T1 | T2'.(7053)


Ссылка на песочницу: https://www.typescriptlang.org/play?jsx=0#code/KYO...

Тот же код, если кому лень в песочницу лезть
enum E1 {
  a = 'a1',
}
enum E2 {
  a = 'a2',
}
type T1 = {
  [key in E1]: string;
};
type T2 = {
  [key in E2]: string;
};

{
  const f = (someObj: T1 | T2, someEnum: typeof E1 | typeof E2): string => {
    return someObj[someEnum.a]; // ts(7053)
  };
}
{
  function f(someObj: T1, someEnum: typeof E1): string;
  function f(someObj: T2, someEnum: typeof E2): string;
  function f(someObj: T1 | T2, someEnum: typeof E1 | typeof E2): string {
    return someObj[someEnum.a]; // ts(7053)
  }
}
{
  type TT =
    | { someObj: T1; someEnum: typeof E1 }
    | { someObj: T2; someEnum: typeof E2 };
  const f = (tt: TT): string => {
    return tt.someObj[tt.someEnum.a]; // ts(7053)
  };
}

Есть ли возможность заставить TS понять, что там не может быть T1 + E2 или T2 + E1?

П.с.: делать проверку на тип внутри функции не вариант, т.к. объект T1/T2 может быть пустым.
  • Вопрос задан
  • 754 просмотра
Решения вопроса 1
WblCHA
@WblCHA Автор вопроса
Судя по активности, адекватного решения нет. Пришлось прибегать к минимальным костылям:
function f(someObj: T1, someEnum: typeof E1): string;
function f(someObj: T2, someEnum: typeof E2): string;
function f(someObj: T1 | T2, someEnum: typeof E1 | typeof E2): string {
    const typedSomeObj = someObj as T1 & T2;
    return typedSomeObj[someEnum.a];
}
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
Lynn
@Lynn
nginx, js, css
Можно вот так:
function f<X extends { [index: string]: string }>(someObj: X, someEnum: keyof X): string  {
    return someObj[someEnum];
}


https://www.typescriptlang.org/play?jsx=0#code/C4T...

Или нужно обязательно ограничиться типами T1, T2?
Ответ написан
bingo347
@bingo347 Куратор тега TypeScript
Crazy on performance...
const f = <T extends T1 | T2>(someObj: T, someEnum: T extends T1 ? typeof E1 : typeof E2) => {
  return (someObj as T1 & T2)[someEnum.a];
};
Ответ написан
@MOCUKOV
Удобно(
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы