Укажите тип возврата в функции TypeScript arrow
Я использую React и Redux и имею типы действий, указанные как интерфейсы, так что мои редукторы могут использовать тегированные типы соединений для повышения безопасности типов.
Итак, у меня есть объявления типов, которые выглядят так:
interface AddTodoAction {
type: "ADD_TODO",
text: string
};
interface DeleteTodoAction {
type: "DELETE_TODO",
id: number
}
type TodoActoin = AddTodoAction | DeleteTodoAction
Я хотел бы создать вспомогательные функции, которые создают эти действия, и я склонен использовать для этого функции стрелок. Если я напишу это:
export const addTodo1 = (text: string) => ({
type: "ADD_TODO",
text
});
Компилятор не может предоставить никакой помощи, чтобы убедиться, что это допустимый AddTodoAction
, потому что тип возврата явно не указан. Я могу явно указать тип возвращаемого значения, выполнив следующее:
export const addTodo2: (text: string) => AddTodoAction = (text: string) => ({
type: "ADD_TODO",
text
})
Но для этого требуется дважды задать аргументы моей функции, поэтому он подробный и трудный для чтения.
Есть ли способ явным образом указать тип возврата при использовании нотации стрелки?
Я подумал попробовать:
export const addTodo3 = (text: string) => <AddTodoAction>({
type: "ADD_TODO",
text
})
В этом случае компилятор теперь вводит возвращаемый тип как AddTodoAction
, но не подтверждает, что возвращаемый объект имеет все соответствующие поля.
Я мог бы решить это, переключившись на другой синтаксис функции:
export const addTodo4 = function(text: string): AddTodoAction {
return {
type: "ADD_TODO",
text
}
}
export function addTodo5(text: string): AddTodoAction {
return {
type: "ADD_TODO",
text
}
}
Любой из этих методов заставит компилятор использовать правильный тип возвращаемого значения и обеспечить, чтобы я правильно установил все поля, но они также более подробные, и они меняют способ "this
" обрабатывается в функции (которая может быть, не проблема, я полагаю.)
Есть ли какие-либо советы относительно наилучшего способа сделать это?
Ответы
Ответ 1
Во-первых, рассмотрите следующие записи из вашего первоначального вопроса:
export const addTodo3 = (text: string) => <AddTodoAction>({
type: "ADD_TODO",
text
})
Используя эту нотацию, вы возвращаете возвращаемый объект типа AddTodoAction
. Тем не менее, объявленный функцией возвращаемого типа остается undefined (и компилятор будет неявно предполагать any
как возвращаемый тип).
Вместо этого используйте следующие обозначения:
export const addTodo3 = (text: string): AddTodoAction => ({
type: "ADD_TODO",
text: text
})
В этом случае опускание требуемого свойства приведет к ожидаемой ошибке компилятора. Например, при отсутствии свойства text
будет генерироваться следующая (желаемая) ошибка:
Type '{ type: "ADD_TODO"; }' is not assignable to type 'TodoAction'.
Type '{ type: "ADD_TODO"; }' is not assignable to type 'DeleteTodoAction'.
Types of property 'type' are incompatible.
Type '"ADD_TODO"' is not assignable to type '"DELETE_TODO"'.
Также см. пример игровая площадка.
Ответ 2
Я думаю, что лучше всего создать интерфейс для вашей функции, который имеет правильные типы, тогда вам нужно указать только этот тип, а не все вложенные типы вашего интерфейса:
interface AddTodoAction {
type: "ADD_TODO",
text: string
};
interface AddTodoActionCreator {
(text: string): AddTodoAction;
};
export const addTodo: AddTodoActionCreator = (text) => ({
type: "ADD_TODO",
text
});