Reputation: 93
I am new to Typescript and trying to use Redux-Toolkit with it in my React application. Here I am trying to create a To Do application with a nested state where each ToDo
contains a array of Comment
. Here are the interfaces:
Comment.ts
export interface Comment {
id: number;
comment: string;
}
ToDo.ts
export interface ToDo {
id: number;
title: string;
description: string;
comments: Array<Comment>;
}
Then in my ToDoSlice
:
export const toDoSlice = createSlice({
name: 'toDoSlice',
initialState: [] as Array<ToDo>,
reducers: {
addToDo: (state, action: PayloadAction<ToDo> ) => {
state.push(action.payload);
},
}
});
The TS compiler throws this on the line state.push(action.payload)
:
TS2345: Argument of type 'ToDo' is not assignable to parameter of type 'WritableDraft<ToDo>'.
Types of property 'comments' are incompatible.
Type 'Comment[]' is not assignable to type 'WritableDraft<Comment>[]'.
Type 'Comment' is not assignable to type 'WritableDraft<Comment>'.
The types of 'ownerDocument.all' are incompatible between these types.
Type 'HTMLAllCollection' is not assignable to type 'WritableDraft<HTMLAllCollection>'.
'number' index signatures are incompatible.
Type 'Element' is not assignable to type 'WritableDraft<Element>'.
Types of property 'attributes' are incompatible.
Type 'NamedNodeMap' is not assignable to type 'WritableDraft<NamedNodeMap>'.
'number' index signatures are incompatible.
Type 'Attr' is not assignable to type 'WritableDraft<Attr>'.
Types of property 'childNodes' are incompatible.
Type 'NodeListOf<ChildNode>' is not assignable to type 'WritableDraft<NodeListOf<ChildNode>>'.
'number' index signatures are incompatible.
Type 'ChildNode' is not assignable to type 'WritableDraft<ChildNode>'.
Types of property 'parentElement' are incompatible.
Type 'HTMLElement | null' is not assignable to type 'WritableDraft<HTMLElement> | null'.
Type 'HTMLElement' is not assignable to type 'WritableDraft<HTMLElement>'.
Types of property 'shadowRoot' are incompatible.
Type 'ShadowRoot | null' is not assignable to type 'WritableDraft<ShadowRoot> | null'.
Type 'ShadowRoot' is not assignable to type 'WritableDraft<ShadowRoot>'.
Types of property 'adoptedStyleSheets' are incompatible.
Type 'CSSStyleSheet[]' is not assignable to type 'WritableDraft<CSSStyleSheet>[]'.
Type 'CSSStyleSheet' is not assignable to type 'WritableDraft<CSSStyleSheet>'.
Types of property 'ownerNode' are incompatible.
Type 'Element | ProcessingInstruction | null' is not assignable to type 'WritableDraft<Element> | WritableDraft<ProcessingInstruction> | null'.
Type 'ProcessingInstruction' is not assignable to type 'WritableDraft<Element> | WritableDraft<ProcessingInstruction> | null'.
I tried to cast the action.payload
to type WritableDraft<ToDo>
, and the error does go away.
addToDo: (state, action: PayloadAction<ToDo> ) =>
{state.push(action.payload as WritableDraft<ToDo>);
},
However, similar problem arises when I try to add a Comment
into an existing ToDo
:
addComment: (state, action: PayloadAction<{toDoId: number, comment: Comment}>) => {
const toDo = state.find(toDo => toDo.id === action.payload.toDoId);
if (toDo) {
toDo.comments.push(action.payload.comment);
}
}
where it gives another error:
Argument of type 'Comment' is not assignable to parameter of type 'WritableDraft<Comment>'.
Type 'Comment' is missing the following properties from type 'WritableDraft<Comment>': data, length, ownerDocument, appendData, and 59 more.
and casting action.payload.comment as WritableDraft<Comment>
won't do. The error almost remains the same.
The version of the dependencies inside of the package.json
:
"dependencies": {
"@reduxjs/toolkit": "^1.9.0",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^13.0.0",
"@testing-library/user-event": "^13.2.1",
"@types/jest": "^27.0.1",
"@types/node": "^16.7.13",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-redux": "^8.0.5",
"react-router-dom": "^6.4.3",
"react-scripts": "5.0.1",
"typescript": "^4.4.2",
"web-vitals": "^2.1.0"
},
Upvotes: 2
Views: 4673
Reputation: 1566
In ToDo.ts
file inside models
folder, you just need to import Comment
interface from Comment.ts
.
import { Comment } from './Comment'
This will fix that typescript error.
Upvotes: 2
Reputation: 31
you should write this:
reducers: {
addToDo: (state, action: PayloadAction<ToDo> ) => {
state.push(action.payload as ToDo);
},
Upvotes: 1