Назначьте правильные типы для функции Reselect createSelector

Изменить: добавлен отрывок package.json

Я пытаюсь внедрить машинописный текст в существующий проект React и столкнулся с трудностями при работе с библиотекой Reselect. Компилятор машинописного текста настаивает на импорте первого определения функции createSelector и не может распознать, что подпись моей функции соответствует другому определению.

Импортируемое определение:

export function createSelector<S, R1, T>(
  selector: Selector<S, R1>,
  combiner: (res: R1) => T,
): OutputSelector<S, T, (res: R1) => T>;

Тот, который я хочу использовать:

export function createSelector<S, R1, R2, T>(
  selectors: [Selector<S, R1>,
              Selector<S, R2>],
  combiner: (res1: R1, res2: R2) => T,
): OutputSelector<S, T, (res1: R1, res2: R2) => T>;

Вот мой фактический код:

// groups.selectors.tsx

import { Selector, createSelector } from 'Reselect';
import { IGroup, IQuestionnaire, IGroupReselect, IState } from '../interfaces';

const getGroups:Selector<IState, IGroup[]> = state => state.groups;
const getQuestionnaires:Selector<IState, IQuestionnaire[]> = state => state.questionnaires;

export const groups = createSelector<IState, IGroup[], IQuestionnaire[], IGroupReselect>(
  [getGroups, getQuestionnaires],
  (g, q) => {

    return g.map(group => Object.assign(
      {},
      group,
      {questionnaires: group.questionnairesIds.map(id => q.find(q => q.id === id))}
    ));
  }
);

И если это мне поможет, вот мой ts.config:

{
  "compilerOptions": {
    "module": "es6",
    "target": "es6",
    "outDir": ".temp",
    "allowSyntheticDefaultImports": true,
    "baseUrl": "src",
    "noImplicitAny": false,
    "sourceMap": false,
    "jsx": "preserve",
    "strict": true,
    "moduleResolution": "node"
  },
  "exclude": [
    "node_modules"
  ],
  "files": [
    "typings.d.ts"
  ]
}

Мне не совсем удобно работать с TypeScript, поэтому в моей реализации определенно что-то не так. Что меня смущает, так это то, что если я пишу простейший повторный селектор, то есть с одним селектором и объединителем арности 1, он проходит проверку типов, из-за чего у меня создается впечатление, что компилятор неправильно выбирает правильное определение среди перегруженных функций в Повторно выберите index.d.ts

Вот соответствующие части моего package.json:

"dependencies": {
    "react": "^15.5.4",
    "react-dom": "^15.5.4",
    "react-redux": "^5.0.5",
    "react-router": "^4.1.1",
    "react-router-dom": "^4.1.1",
    "redux": "^3.6.0",
    "redux-devtools-extension": "^2.13.2",
    "redux-thunk": "^2.2.0",
    "reselect": "^3.0.1"
  },
  "devDependencies": {
    "@types/react": "^15.0.25",
    "@types/react-router-dom": "^4.0.4",
    "@types/redux-thunk": "^2.1.0",
    "typescript": "^2.3.3"
  },

person Tristan Hamel    schedule 31.05.2017    source источник
comment
Я бы сначала проверил, есть ли у вас версия Reselect index.d.ts, на которую вы ссылались. Поддержка массивов селекторов не добавлялась до недавнего времени (кажется, версия 3.0). Вы можете вообще опустить массив; он не требуется при повторном выборе (хотя в большинстве примеров он используется).   -  person Radio-    schedule 01.06.2017
comment
Это действительно может быть проблема с моими версиями зависимостей. Что касается селекторов массивов, я запускаю reselect 3.0.1, так что это не должно быть проблемой.   -  person Tristan Hamel    schedule 03.06.2017


Ответы (1)


Я могу ошибаться, но из этой этой проблемы кажется, что она вызвана тем, как язык выводит ваш разнородный массив [getGroups, getQuestionnaires] как массив, а не как кортеж.

Принуждение первого аргумента к типу кортежа заставит его работать, но приведет к ненужному шаблону.

const getGroups:Selector<IState, IGroup[]> = state => state.groups;
const getQuestionnaires:Selector<IState, IQuestionnaire[]> = state => 
  state.questionnaires;

const selectors: [Selector<IState, IGroup[]>, Selector<IState, IQuestionnaire[]>] = [getGroups, getQuestionnaires]

export const groups = createSelector<IState, IGroup[], IQuestionnaire[], IGroupReselect>(
  selectors,
  (g, q) => {

    return g.map(group => Object.assign(
      {},
      group,
      {questionnaires: group.questionnairesIds.map(id => q.find(q => q.id === id))}
    ));
  }
);
person Evan Sebastian    schedule 01.06.2017