funciones - Especifique el tipo de retorno en la función de flecha TypeScript
funciones flecha javascript (2)
Estoy usando React y Redux y tengo tipos de acción especificados como interfaces, por lo que mis reductores pueden aprovechar los tipos de unión etiquetados para mejorar la seguridad de los tipos.
Entonces, tengo declaraciones de tipo que se ven así:
interface AddTodoAction {
type: "ADD_TODO",
text: string
};
interface DeleteTodoAction {
type: "DELETE_TODO",
id: number
}
type TodoAction = AddTodoAction | DeleteTodoAction
Me gustaría hacer funciones auxiliares que creen estas acciones, y tiendo a usar funciones de flecha para esto. Si escribo esto:
export const addTodo1 = (text: string) => ({
type: "ADD_TODO",
text
});
El compilador no puede proporcionar ninguna ayuda para asegurarse de que se trata de una
AddTodoAction
válida porque el tipo de retorno no se especifica explícitamente.
Puedo especificar el tipo de retorno explícitamente haciendo esto:
export const addTodo2: (text: string) => AddTodoAction = (text: string) => ({
type: "ADD_TODO",
text
})
Pero esto requiere especificar mis argumentos de función dos veces, por lo que es detallado y difícil de leer.
¿Hay alguna manera de especificar el tipo de retorno explícitamente cuando uso la notación de flecha?
He pensado en probar esto:
export const addTodo3 = (text: string) => <AddTodoAction>({
type: "ADD_TODO",
text
})
En este caso, el compilador ahora infiere el tipo de retorno como
AddTodoAction
pero no valida que el objeto que estoy devolviendo tenga todos los campos apropiados.
Podría resolver esto cambiando a una sintaxis de función diferente:
export const addTodo4 = function(text: string): AddTodoAction {
return {
type: "ADD_TODO",
text
}
}
export function addTodo5(text: string): AddTodoAction {
return {
type: "ADD_TODO",
text
}
}
Cualquiera de estos métodos hará que el compilador use el tipo de retorno correcto y obligue a que haya configurado todos los campos de manera adecuada, pero también son más detallados y cambian la forma en que ''
this
'' se maneja en una función (lo que puede no ser un problema) , Supongo.)
¿Hay algún consejo sobre la mejor manera de hacer esto?
Creo que su mejor opción es crear una interfaz para su función que tenga los tipos correctos, luego solo necesita especificar ese tipo, no todos los tipos anidados de su interfaz:
interface AddTodoAction {
type: "ADD_TODO",
text: string
};
interface AddTodoActionCreator {
(text: string): AddTodoAction;
};
export const addTodo: AddTodoActionCreator = (text) => ({
type: "ADD_TODO",
text
});
Actualización: cómo hacer esto con tipos
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}; };
Primero, considere la siguiente notación de su pregunta original:
export const addTodo3 = (text: string) => <AddTodoAction>({
type: "ADD_TODO",
text
})
Usando esta notación, usted convierte el objeto devuelto al tipo
AddTodoAction
.
Sin embargo, el tipo de retorno declarado de la función aún no está definido (y el compilador asumirá implícitamente
any
como tipo de retorno).
Use la siguiente notación en su lugar:
export const addTodo3 = (text: string): AddTodoAction => ({
type: "ADD_TODO",
text: text
})
En este caso, omitir una propiedad requerida generará el error esperado del compilador.
Por ejemplo, omitir la propiedad de
text
generará el siguiente error (deseado):
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"''.
Vea también el ejemplo del patio de recreo .