TS2322 Тип X |Y |Z [] нельзя назначить типу Z [] - Typescript - PullRequest
0 голосов
/ 03 октября 2019

Я новичок в 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;

Я ожидал, что сужение типа сработает на моем редукторе, но я получаю следующие две ошибки в ответеоператоры в редукторе:

Ошибка: (14, 31) TS2322: Тип 'Разговор |ChatMessage |Разговор [] 'нельзя назначить типу' Разговор [] '. Типу «Беседа» не хватает следующих свойств из типа «Беседа []»: длина, всплывающее, толчок, конкат и еще 26.

Ошибка: (18, 17) TS2322: Тип '(Conversation | ChatMessage | Conversation []) []' нельзя назначить типу 'Conversation []'. Тип 'Разговор |ChatMessage |Разговор [] 'не может быть назначен типу' Разговор '. В типе 'ChatMessage' отсутствуют следующие свойства из типа 'Диалог': title, unreadMessages, messages

Почему Conversaion [] нельзя назначить для Conversation []?

Редактировать 1: Этот кусок является виновником:

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

Когда я изменяю это на строку const, как это:

export const UNSEEN_MESSAGE_RECEIVED: 'UNSEEN_MESSAGE_RECEIVED';

проблема решена. Я не знаю, как typeof отличается между ними двумя. Они оба строки. Но что происходит с компилятором, я не знаю.

1 Ответ

0 голосов
/ 04 октября 2019

Я не совсем уверен, почему 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 выводит, что ваше вложенное свойство имеет тип string (как вы узнали). Если вы используете const в строке типа примитива, значение никогда не может быть изменено - таким образом, тип может быть сужен от строки до 'UNSEEN_MESSAGE_RECEIVED'. Если вы вложите это внутрь объекта, сама ссылка на объект всегда будет одинаковой, но вы можете изменить свойства этого объекта. Таким образом, 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'
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...