TS2322类型X | Y | Z []无法分配给Z []类型-Typescript

时间:2019-10-03 20:58:35

标签: typescript redux

我是Typescript的新手,正在将我的本机代码库迁移到Typescript。我尝试解决一个奇怪的错误,但无法解决。 这是减速器:

const INITIAL_STATE: MessagingState = {
conversations: [],
send: [],
read: []
};

export default function (state: MessagingState = INITIAL_STATE, action: 
UserMessagingActionTypes): MessagingState {
switch (action.type) {
    case USER_CONVERSATIONS_RECEIVED:
        return {...state, conversations: action.payload};
    case USER_CONVERSATION_RECEIVED:
        return {
            ...state,
            conversations: [...state.conversations, action.payload]
        };
    default:
        return state;
   }
}

export interface MessagingState {
conversations: Conversation[]
send: StompMessage[]
read: ChatMessage[]
}

和操作类型:

export interface UserConversationsReceived {
type: typeof USER_CONVERSATIONS_RECEIVED,
payload: Conversation[]
}

export interface UserConversationReceived {
type: typeof USER_CONVERSATION_RECEIVED,
payload: Conversation
}

export interface UserStompUnseenMessageReceived  {
type: typeof MESSAGING_ACTIONS.USER.UNSEEN_MESSAGE_RECEIVED,
payload: ChatMessage
}


export const MESSAGING_ACTIONS = {
  USER:{UNSEEN_MESSAGE_RECEIVED: 'UNSEEN_MESSAGE_RECEIVED'}
}
export const USER_CONVERSATION_RECEIVED= 'USER_CONVERSATION_RECEIVED';
export const USER_CONVERSATIONS_RECEIVED = 'USER_CONVERSATIONS_RECEIVED';

export type UserMessagingActionTypes =
UserConversationsReceived
| UserConversationReceived
| UserStompUnseenMessageReceived;

我原本希望在减速器上使用类型变窄,但是在减速器的return语句中出现以下两个错误:

错误:(14,31)TS2322:键入“对话| ChatMessage |不能将“ Conversation []”分配给“ Conversation []”类型。   类型“对话”缺少类型“对话[]”中的以下属性:长度,弹出,推入,连续和另外26个。

错误:(18,17)TS2322:类型'(Conversation | ChatMessage | Conversation [])[]'无法分配给类型'Conversation []'。   输入“会话| ChatMessage |不能将“ Conversation []”分配给“ Conversation”类型。     类型“ ChatMessage”缺少类型“对话”中的以下属性:标题,unreadMessages,消息

为什么不能将Conversaion []分配给Conversation []?

修改1:  这是罪魁祸首:

export const MESSAGING_ACTIONS = {
  USER:
   {UNSEEN_MESSAGE_RECEIVED: 'UNSEEN_MESSAGE_RECEIVED'}
}

当我将其更改为这样的字符串常量时:

export const UNSEEN_MESSAGE_RECEIVED: 'UNSEEN_MESSAGE_RECEIVED';

问题已解决。我不知道两者之间的 typeof 有何不同。它们都是字符串。但是我不知道编译器怎么了。

1 个答案:

答案 0 :(得分:0)

我不太确定为什么TypeScript无法根据您的情况缩小类型。我在TypeScript Playground.

上工作了

请注意,您的操作的类型必须是立即为其赋值的字符串,这些字符串要么没有类型定义export const USER_CONVERSATION_RECEIVED = 'USER_CONVERSATION_RECEIVED',要么具有特定的字符串作为类型定义,例如export const USER_CONVERSATION_RECEIVED: 'USER_CONVERSATION_RECEIVED' = 'USER_CONVERSATION_RECEIVED'

export const USER_CONVERSATION_RECEIVED = 'USER_CONVERSATION_RECEIVED'; // Correct
export const USER_CONVERSATION_RECEIVED: 'USER_CONVERSATION_RECEIVED' = 'USER_CONVERSATION_RECEIVED'; // Correct
export const USER_CONVERSATION_RECEIVED: string = 'USER_CONVERSATION_RECEIVED'; // Wrong

似乎TypeScript推断您的嵌套属性为字符串类型(如您所知)。如果在原始类型字符串上使用const,则永远不能更改该值-因此,可以将类型从字符串缩小为“ UNSEEN_MESSAGE_RECEIVED”。如果将其嵌套在对象内,则对象引用本身始终是相同的-但您可以更改该对象的属性。因此,TypeScript必须假定类型为字符串(并且不能进一步缩小类型),因为它可以在某个时候更改(因为默认情况下它不是只读的)。

很明显,一种解决方法是不嵌套它。或者,您可以为Typescript提供更窄的类型,尽管看起来很冗长:

export const MESSAGING_ACTIONS: { 
    USER: {
        UNSEEN_MESSAGE_RECEIVED: 'UNSEEN_MESSAGE_RECEIVED'
    }
} = {
    USER:{
        UNSEEN_MESSAGE_RECEIVED: 'UNSEEN_MESSAGE_RECEIVED'
    }
}

// or with an interface

export interface MessagingActions {
    USER: {
        UNSEEN_MESSAGE_RECEIVED: 'UNSEEN_MESSAGE_RECEIVED'
    }
}

export const MESSAGING_ACTIONS:MessagingActions = {
    USER:{
        UNSEEN_MESSAGE_RECEIVED: 'UNSEEN_MESSAGE_RECEIVED'
    }
}