Возможна ли работа с элементами массива с разными типами объединения без ошибки не присваивается параметру типа 'никогда'?

type GenericElement<T> = {
  set: Setter<T>;
  state: T;
} 

type Setter<T> = (state: T) => void

type GenericElements = Array< GenericElement<string> |  GenericElement<number>>

const genericElements = [{
  set: (state: string) => console.log(state),
  state: 'stateValue'
}, {
  set: (state: number) => console.log(state),
  state: 123
}]

genericElements.map(({set, state}) => set(state))
// ---------------------------------------|

/**
 * Argument of type 'string | number' is not assignable to parameter of type 'never'.
 * Type 'string' is not assignable to type 'never'.(2345)
*/

Example on TS детская площадка

Возможно ли реализовать это без этой проблемы, или как сделать так, чтобы предложенная структура могла обрабатывать ее set(state) обычным способом без шаблонов, таких как выполнение этой операции для каждого дочернего элемента вручную или перекодирование, такое как [() => set1(state1), () => setN(stateN)]?


person eLeontev    schedule 15.07.2020    source источник
comment
Отвечает ли это на ваш вопрос? Как ввести параметризацию кортежа?   -  person HTNW    schedule 15.07.2020
comment
@HTNW В ответе, который вы связали, вы в конечном итоге вставили универсальную количественную оценку внутри массива, то есть вместо Array<Foo<string>|Foo<number>> в итоге получилось бы Array<FooExistentiallyQuantified>. Это действительно работает, если у вас есть Foo<string>|Foo<number>? Кажется, что он не может использовать existentialize-подобный nat trafo внутри map, поэтому приходится приводить Foo<string>|Foo<number> к чему-то вроде Foo<any>, и в этот момент вся предыдущая конструкция кажется ненужной. Есть ли лучшие решения?   -  person Andrey Tyukin    schedule 16.07.2020
comment
@AndreyTyukin Хм, ты прав. Я не уверен, что что-то действительно работает для настоящего Array<Foo<string>|Foo<number>>. Я думаю, что нам в основном нужен способ сказать, что, поскольку одна и та же функция проверяет типы в обеих ветвях, она должна проверять тип в объединении. Прямо сейчас компилятор разрушает корреляцию между set и state. Близкое голосование отслежено.   -  person HTNW    schedule 16.07.2020


Ответы (1)


После непрерывных поисков я нашел способ, который может работать для меня.

Link to

enum genericTypes {
    stringTypes = 'stringTypes',
    numberTypes = 'numberTypes',
}
const {numberTypes, stringTypes} = genericTypes;

type GenericElement<T extends genericTypes> = {
    set: Setter<T>;
    state: State<T>;
};

type State<T extends genericTypes> = T extends genericTypes.numberTypes ? number : string;

type States = {
    [numberTypes]: State<genericTypes.numberTypes>;
    [stringTypes]: State<genericTypes.stringTypes>;
};

type Setter<T extends genericTypes> = (state: State<T>) => void;

type Setters = {
    [numberTypes]: Setter<genericTypes.numberTypes>;
    [stringTypes]: Setter<genericTypes.stringTypes>;
};

const setters: Setters = {
    [numberTypes]: (state: State<genericTypes.numberTypes>) => console.log(state),
    [stringTypes]: (state: State<genericTypes.stringTypes>) => console.log(state),
};

const states: States = {
    [numberTypes]: 123,
    [stringTypes]: '123',
};

type GenericElements = Array<GenericElement<genericTypes>>;

const genericElements: GenericElements = [
    { set: setters.numberTypes, state: states.numberTypes },
    { set: setters.stringTypes, state: states.stringTypes },
];

genericElements.map(({ set, state }) => set(state));

Я буду продолжать расследование, чтобы наконец понять. Если кто-нибудь может рассмотреть предложение с обратной связью, я буду очень признателен.

person eLeontev    schedule 17.07.2020