Reputation: 181
running into a TS2339 typing error with TS, stating that I can't find the parameter being defined in the interface type. Below are the two files that I have in question:
const res = yield call(fetchAllBooks, action.param);
IBookAction
from ../actions
) does not exist on IBookAction
and also on ILoadSearchableBooks
import { takeEvery, call, put } from 'redux-saga/effects';
import { Action, IBookAction } from '../actions';
import { fetchAllBooks } from '../service/books-service';
import { Book } from '../classes';
export default function* watcherSaga() {
yield takeEvery(Action.FETCH_SEARCHABLE_BOOKS, searchableBooksSaga);
}
function* searchableBooksSaga(action: IBookAction) {
try {
const res = yield call(fetchAllBooks, action.param);
const searchableBooks = res.data.reduce((books: Array<Book>, b: any) => {
books.push(new Book(b));
return books;
}, [])
yield put({ type: Action.LOAD_SEARCHABLE_BOOKS, searchableBooks });
} catch (e) {
yield put({ type: Action.FETCH_ERROR, error: e});
}
}
And below is the file where I had defined the interfaces:
import { Action } from './action-constants';
import { Book } from '../classes';
export interface IAction {
type: Action
}
// TODO: refactor into other action files if it gets too large.
// Nav Actions
export interface INavigateAction extends IAction {
payload: string
}
export function navigateAction(newState: any): INavigateAction {
console.log('Navigating to::', newState);
return { type: Action.NAVIGATE_TO, payload: newState }
}
// Book Actions
export interface IFetchSearchableBookAction extends IAction {
param: any // TODO: properly type the parameters.
}
export function fetchSerachableBooks(param: any): IBookAction {
console.log('Fetching Searchable Books:', param);
return { type: Action.FETCH_SEARCHABLE_BOOKS, param }
}
export interface ILoadSearchableBooks extends IAction {
searchableBooks: Array<Book>
}
export { Action } from './action-constants';
export type IBookAction = IFetchSearchableBookAction | ILoadSearchableBooks;
As see in the last line, I am exporting IBookAction
types, one of which is the IFetchSearchableBookAction
which has the param
property.
Full error that I am getting:
TS2339: Property 'param' does not exist on type 'IBookAction'.
Property 'param' does not exist on type 'IFetchSearchableBookAction'
Upvotes: 0
Views: 1362
Reputation: 2904
Because IBookAction
can be either IFetchSearchableBookAction
or ILoadSearchableBooks
, and ILoadSearchableBooks
does not have param
prop. Meaning, it can only be 50% sure that action
has param
prop, but not 100%.
What if action
is ILoadSearchableBooks
and not IFetchSearchableBookAction
, then param
will probably be undefined
.
Workaround is to type guard to let Typescript know that this action
is indeed IFetchSearchableBookAction
and not ILoadSearchableBooks
.
For example:
function searchableBooksSaga(action: ILoadSearchableBooks | IFetchSearchableBookAction) {
if ('param' in action) {
const param = action.param;
} else {
const books = action.searchableBooks;
}
}
See more info about how to type guard in Typescript here
Upvotes: 1