Подтвердить что ты не робот

Укажите тип возврата в функции 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" обрабатывается в функции (которая может быть, не проблема, я полагаю.)

Есть ли какие-либо советы относительно наилучшего способа сделать это?

4b9b3361

Ответ 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
});