To define the return type for the function, we have to use the ':' symbol just after the parameter of the function and before the body of the function in TypeScript. The function body's return value should match with the function return type; otherwise, we will have a compile-time error in our code.
The most common and standard way of returning an object from an arrow function would be to use the longform syntax: const createMilkshake = (name) => { return { name, price: 499 }; }; const raspberry = createMilkshake('Raspberry'); // 'Raspberry' console.
Introduction to TypeScript function typesThe function type accepts two arguments: x and y with the type number . The type of the return value is number that follows the fat arrow ( => ) appeared between parameters and return type.
The function's return type is string. Line function returns a string value to the caller. This is achieved by the return statement. The function greet() returns a string, which is stored in the variable msg.
First, consider the following notation from your original question:
export const addTodo3 = (text: string) => <AddTodoAction>({
type: "ADD_TODO",
text
})
Using this notation, you typecast the returned object to the type AddTodoAction
. However, the function's declared return type is still undefined (and the compiler will implicitly assume any
as return type).
Use the following notation instead:
export const addTodo3 = (text: string): AddTodoAction => ({
type: "ADD_TODO",
text: text
})
In this case, omitting a required property will yield the expected compiler error. For example, omitting the text
property will generate the following (desired) error:
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"'.
Also see the playground example.
I think your best bet is to create an interface for your function which has the right types, then you only need to specify that type, not all the nested types of your interface:
interface AddTodoAction {
type: "ADD_TODO",
text: string
};
interface AddTodoActionCreator {
(text: string): AddTodoAction;
};
export const addTodo: AddTodoActionCreator = (text) => ({
type: "ADD_TODO",
text
});
Update: How to do this with types
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};
};
There are 2 ways of achieving this with proper typing and minimal code:
interface AddTodoAction {
type: "ADD_TODO",
text: string
};
// Because the this keyword works different in arrow functions these
// 2 implementations are different in some cases:
// arrow function form/ function expression
const addTodo1 = (text: string): AddTodoAction => ({
type: "ADD_TODO",
text: text
})
// function declaration form
function addTodo2 (text: string): AddTodoAction {
return ({
type: "ADD_TODO",
text: text
})
}
Now the TS compiler can check the returned types. For example:
const todo = addTodo1('hi');
// Following gives TS compile time error
// addTodo1 returns AddTodoAction which does not have id on the type
const id = todo.id // Property 'id' does not exist on type 'AddTodoAction'.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With