228 votes

Spécifier le type de retour en caractères d'imprimerie flèche fonction

Je suis à l'aide de Réagir et de Redux et ont des types spécifiés comme interfaces, de sorte que mon réducteurs peuvent profiter de tagged types d'union pour l'amélioration de la sécurité de type.

Donc, j'ai des déclarations de types qui ressemblent à ceci:

interface AddTodoAction {
    type: "ADD_TODO",
    text: string
};

interface DeleteTodoAction {
    type: "DELETE_TODO",
    id: number
}

type TodoAction = AddTodoAction | DeleteTodoAction

Je voudrais faire des fonctions d'assistance qui créer ces actions, et j'ai tendance à utiliser la flèche pour le présent. Si j'écris ceci:

export const addTodo1 = (text: string) => ({
    type: "ADD_TODO",
    text
});

Le compilateur ne peut pas fournir toute aide à ce que ce soit valable, AddTodoAction parce que le type de retour n'est pas spécifiée explicitement. Je peux spécifier le type de retour explicitement en faisant ceci:

export const addTodo2: (text: string) => AddTodoAction = (text: string) => ({
    type: "ADD_TODO",
    text
})

Mais cela nécessite de spécifier mes arguments d'une fonction deux fois, donc c'est verbeux et plus difficile à lire.

Est il possible que je peux spécifier le type de retour explicitement lors de l'utilisation de la flèche de la notation?

J'ai pensé à essayer ceci:

export const addTodo3 = (text: string) => <AddTodoAction>({
    type: "ADD_TODO",
    text
})

Dans ce cas, le compilateur déduit le type de retour comme AddTodoAction mais cela ne veut pas valider le fait que l'objet que je suis de retour a tous les champs appropriés.

Je pourrais résoudre ce par de passer à une autre syntaxe de la fonction:

export const addTodo4 = function(text: string): AddTodoAction {
    return {
        type: "ADD_TODO",
        text
    }
}

export function addTodo5(text: string): AddTodoAction {
    return {
        type: "ADD_TODO",
        text
    }
}

Une de ces méthodes va provoquer le compilateur à utiliser le bon type de retour et faire valoir ce que j'ai mis tous les champs correctement, mais ils sont aussi plus détaillé et ils changent le chemin"this"est traitée dans une fonction (qui peut ne pas être un problème, je suppose.)

Est-il des conseils sur la meilleure façon de le faire?

251voto

helmbert Points 1870

Tout d'abord, considérons la notation suivante à partir de votre question initiale:

export const addTodo3 = (text: string) => <AddTodoAction>({
    type: "ADD_TODO",
    text
})

En utilisant cette notation, vous transtypage de l'objet retourné type AddTodoAction. Cependant, la fonction déclarée de type de retour est toujours pas défini (et le compilateur supposent implicitement any comme type de retour).

Utiliser la notation suivante à la place:

export const addTodo3 = (text: string): AddTodoAction => ({
    type: "ADD_TODO",
    text: text
})

Dans ce cas, l'omission d'un nécessaire propriété de rendement attendus d'erreur du compilateur. Par exemple, l'omission de l' text propriété de générer de la suite (désiré) erreur:

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"'.

Voir aussi l' aire de jeux exemple.

5voto

azium Points 11023

Je pense que votre meilleur pari est de créer une interface pour votre fonction, qui a le droit de types, alors vous avez seulement besoin de spécifier que le type, pas tous les types imbriqués de votre interface:

interface AddTodoAction {
    type: "ADD_TODO",
    text: string
};

interface AddTodoActionCreator {
    (text: string): AddTodoAction;
};

export const addTodo: AddTodoActionCreator = (text) => ({
    type: "ADD_TODO",
    text
});

Mise à jour: Comment faire avec les types de

export interface GeneralAction<T> {
    type: string;
    payload: T;
}

export interface GeneralActionCreator<T> {
    (payload: T): GeneralAction<T>;
}

export const SAVE_EVENT = 'SAVE_EVENT';

export const SaveEvent: GeneralActionCreator<UserEvent> = (payload) => { return {type: SAVE_EVENT, payload}; };

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X