Recoilのselector内でget関数でエラーが出る
解決したいこと
selectorで全タスク、完了タスク、未完了タスクの数を参照して、出力したい。selectorを管理しているファイル内のget関数でオーバーロードのエラーが出されてしまう。
発生している問題・エラー
(property) ReadOnlySelectorOptions<number>.get: (opts: {
get: GetRecoilValue;
getCallback: GetCallback;
}) => number | Promise<number> | RecoilValue<number> | Loadable<number> | WrappedValue<...>
この呼び出しに一致するオーバーロードはありません。
2 中 1 のオーバーロード, '(options: ReadWriteSelectorOptions<number>): RecoilState<number>' により、次のエラーが発生しました。
型 '({ get }: { get: GetRecoilValue; getCallback: GetCallback; }) => { totalNum: number; totalCompletedNum: number; totalUnCompletedNum: number; }' を型 '(opts: { get: GetRecoilValue; getCallback: GetCallback; }) => number | Promise<number> | RecoilValue<number> | Loadable<number> | WrappedValue<...>' に割り当てることはできません。
selector.tsでセレクターを管理しており、returnにおいてオブジェクトで複数の値を返すと上記エラーが出現してしまう。
該当するソースコード
selector.ts
import { selector } from 'recoil';
import { todoListState } from './atom';
export const todoListStatusState = selector<number>({
key: 'todoListStatusState',
get: ({ get }) => { //NG
const todoList = get(todoListState);
const totalNum = todoList.length;
const totalCompletedNum = todoList.filter((item) => item.isComplete).length;
const totalUnCompletedNum = totalNum - totalCompletedNum;
return { totalNum, totalCompletedNum, totalUnCompletedNum };
},
});
TodoListStatus.tsx
//こちらでもuseRecoilValueで参照しようとしてもselectorでエラーが出ているため、できない
import React from 'react';
import { useRecoilValue } from 'recoil';
import { todoListStatusState } from '../State/selector';
const TodoListStatus = () => {
const { totalNum, totalCompletedNum, totalUnCompletedNum } =
useRecoilValue(todoListStatusState);
return (
<div>
<ul>
<li>Todoの登録数: {totalNum}</li>
<li>完了数: {totalCompletedNum}</li>
<li>未完了数: {totalUnCompletedNum}</li>
</ul>
</div>
);
};
export default TodoListStatus;
atom.ts
import { atom } from 'recoil';
import { DATA } from '../types/DataType';
export const todoListState = atom<Array<DATA>>({
key: 'todoListState',
default: [
{
id: 0,
title: '送信設定',
isComplete: false,
},
],
});
DataType.ts
export type DATA = {
id: number;
title: string;
isComplete: boolean;
};
export type ITEMPROPS = {
todo: DATA;
};
自分で試したこと
今回はRecoilのドキュメントを参考にして、記述していました。
オーバーロードということだったので、TypeScriptでのオーバーロードについて調査した。
こちらの記事
関数の引数に複数の型を定義することだそうだ。
という文言を拝見して、設定した型の指定仕方に問題があるのかなと考えた。
↓
selectorメソッドに型を指定するのに、リテラル型にすればいいのかなと推測。しかし、具体的な型が分からずanyにすることで一時退避はできたが、TypeScriptの強みを消してしまっているので、anyは避けたい(一時的に全てのエラーは無くなった)。
selector.ts
import { selector } from 'recoil';
import { todoListState } from './atom';
export const todoListStatusState = selector<number | any>({
key: 'todoListStatusState',
get: ({ get }) => {
const todoList = get(todoListState);
const totalNum = todoList.length;
const totalCompletedNum = todoList.filter((item) => item.isComplete).length;
const totalUnCompletedNum = totalNum - totalCompletedNum;
return { totalNum, totalCompletedNum, totalUnCompletedNum };
},
});
0