基于未定义的联合类型的 React Redux 编译错误

Compilation error with React Redux based on a union type with undefined

我目前正在做一个关于将 Redux 与 React 结合使用的教程,并决定使用 Typescript 来完成。我收到一个编译错误,其中我的商店的状态是 {posts: PostType[]} 类型。但是我收到一条错误消息说

Type '{ posts: PostType[]; } | undefined' is not assignable to type '{ posts: PostType[]; }'

我不确定该怎么做,因为在我自己的代码中我没有明确建议帖子可能未定义。以下是代码中的相关点。

// The component using redux
handleClick = () => {
        const post = this.props.post! as PostType
        this.props.deletePost(post.id)
}

const mapStateToProps = (state: {posts: PostType[]}, ownProps: Props) => {
    return {
        post: state.posts.find(post => {
            return post.id === parseInt(ownProps.match.params.post_id);
        })
    }
}

const mapDispatchToProps = (dispatch: any) => {
    return {
        deletePost: (id: number) => {dispatch({type: 'DELETE_POST', id: id})}
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(Post);
// The reducer
import { PostType } from "../components/Home";

const initState = {
    posts: [{id: 1, title: 'Doctors hate him', body: 'Discover the new trick to stay young', userId: 3}, 
            {id: 2, title: 'Fresh donuts', body: 'Hand-glazed', userId: 4}, 
            {id: 3, title: 'Duque dimite', body: 'El presidente colobiano dio su renuncia', userId: 5}]
}

const rootReducer = (state: {posts: PostType[]}  = initState, action: {type: string, id: number}) => { 
    if (action.type === 'DELETE_POST') {
        return {
            ...state,
            posts: state.posts.filter(post => post.id !== action.id)
        }
    }
}   


export default rootReducer;

我注意到的一件奇怪的事情是,如果我从 rootReducer 函数中删除 if 语句,我的代码可以正常转换。我真的很困惑。我确实尝试研究这个问题,我发现了一些暗示它可能与 --strictNullChecks 标志与 redux 不兼容有关的东西,但我不确定。感谢您的帮助。

编辑:堆栈跟踪 + 下面的组件

Post.tsx:48 Uncaught TypeError: Cannot read property 'posts' of undefined
    at Function.mapStateToProps [as mapToProps] (Post.tsx:48)

指的是这个

const mapStateToProps = (state: {posts: PostType[]} , ownProps: Props) => {
    return {
        post: state.posts.find(post => {  // this line causes the error
            return post.id === parseInt(ownProps.match.params.post_id);
        })
    }
}

虽然我认为上面的代码更相关,但我将在下面保留组件代码。

interface PostProps {
    post_id: string
}

interface Props extends RouteComponentProps<PostProps> {
    post?: PostType
    deletePost: (id: number) => void
}

class Post extends Component<Props, {}> {

    handleClick = () => {
        const post = this.props.post! as PostType
        this.props.deletePost(post.id)
    }

    render() {
        let post;
        if (this.props.post !== undefined) {
            const postData = this.props.post! as PostType
            post = 
            <div className="post">
                <h4 className="center">{postData.title}</h4>
                <p>{postData.body}</p>
                <div className="center">
                    <button className="btn grey" onClick={this.handleClick}>Delete Post</button>
                </div>
            </div>;
        } else {
            post = <h4>Loading post...</h4>;
        }
        return (
            <div className="container">
                {post}
            </div>
        );
    }
}

事实证明这是我的reducer 的错误。我之前检查了参数的 action.type,然后 returned 了一个新的状态,但是如果它不是那种类型,我 returned void 认为它很好,因为我没有在我的代码中传递任何其他类型的操作。实际上,reducer 在后台被调用,因此它导致了这个错误,因为现在状态是未定义的。所以总是 return 现有状态作为减速器中的默认值!

仅修复以下必要内容:

const rootReducer = (state: {posts: PostType[]}  = initState, action: {type: string, id: number}) => { 
    if (action.type === 'DELETE_POST') {
        return {
            ...state,
            posts: state.posts.filter(post => post.id !== action.id)
        }
    }
    return {
        ...state      // We do this because the reducer is called by something that was not our dispatch
    }
}