我是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 有何不同。它们都是字符串。但是我不知道编译器怎么了。
答案 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'
}
}