#typescript
#typescript
Вопрос:
У меня есть приведенный ниже (значительно упрощенный для целей этого примера) код.
type Todo = {
id: string;
text: string;
};
type Action =
| { type: 'DELETE'; payload: string }
| { type: 'CREATE'; payload: Todo }
function reducer(state: Todo[], { type, payload }: Action) {
switch (type) {
case 'CREATE':
const trimmedText = payload.text.trim(); // TS Error - Property 'text' does not exist on type 'string'
return [...state, payload];
case 'DELETE':
return state.filter((todo) => todo.id !== payload); // TS still thinks, at this line, that the payload could be either string or Todo
default:
throw new Error();
}
}
Вопросы
-
Почему typescript не распознает, что в случае «CREATE» полезная нагрузка не может быть строкой?
-
И в случае «УДАЛЕНИЯ» почему Typescript не распознает, что полезная нагрузка должна быть строкой?
Комментарии:
1. Typescript недостаточно умен, чтобы вводить 2 независимые переменные, это сработало бы, если бы вы не использовали деструктурирование.
2. @zerkms Ты легендарный приятель! Я потратил часы, пытаясь разобраться в этом, хех. Не могли бы вы указать это в ответе, чтобы я мог пометить его как принятое правильное решение для этого?
Ответ №1:
Насколько я помню, на данный момент это ограничение typescript: он пока не может сузить типы для 2 «независимых» переменных. На данный момент я не могу найти соответствующую проблему github, но я думаю, что видел ее.
Тем не менее, чтобы заставить его работать, вместо этого работайте напрямую с action: Action
переменной и не разрушайте ее.
type Action =
| { type: 'DELETE'; payload: string }
| { type: 'CREATE'; payload: Todo }
function reducer(state: Todo[], action: Action) {
switch (action.type) {
case 'CREATE':
// ...
case 'DELETE':
// ...
default:
throw new Error();
}
}