在 TypeScript 箭头函数中指定返回类型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40270393/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 07:25:47  来源:igfitidea点击:

Specify return type in TypeScript arrow function

typescript

提问by Brian Hanechak

I am using React and Redux and have action types specified as interfaces, so that my reducers can take advantage of tagged union types for improved type safety.

我正在使用 React 和 Redux,并将操作类型指定为接口,以便我的 reducer 可以利用标记的联合类型来提高类型安全性。

So, I have type declarations that look like this:

所以,我有如下所示的类型声明:

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

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

type TodoAction = AddTodoAction | DeleteTodoAction

I'd like to make helper functions that create these actions, and I tend to use arrow functions for this. If I write this:

我想制作创建这些动作的辅助函数,我倾向于为此使用箭头函数。如果我这样写:

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

The compiler can't provide any help in making sure this is a valid AddTodoActionbecause the return type isn't specified explicitly. I can specify the return type explicitly by doing this:

编译器无法提供任何帮助以确保这是有效的,AddTodoAction因为未明确指定返回类型。我可以通过这样做显式指定返回类型:

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

But this requires specifying my function arguments twice, so it's verbose and harder to read.

但这需要两次指定我的函数参数,因此它很冗长且难以阅读。

Is there a way I can specify the return type explicitly when using arrow notation?

有没有办法在使用箭头表示法时显式指定返回类型?

I've thought of trying this:

我想过试试这个:

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

In this case, the compiler now infers the return type as AddTodoActionbut it's doesn't validate that the object I'm returning has all of the appropriate fields.

在这种情况下,编译器现在推断返回类型为,AddTodoAction但它不会验证我返回的对象是否具有所有适当的字段。

I could solve this by switching to a different function syntax:

我可以通过切换到不同的函数语法来解决这个问题:

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

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

Either of these methods will cause the compiler to use the correct return type and enforce that I have set all fields appropriately, but they are also more verbose and they change the way 'this' is handled in a function (which may not be an issue, I suppose.)

这两种方法中的任何一种都会导致编译器使用正确的返回类型并强制我适当地设置所有字段,但它们也更加冗长,并且它们改变了this在函数中处理“ ”的方式(这可能不是问题,我想。)

Is there any advice about the best way to do this?

有没有关于最好的方法来做到这一点的建议?

回答by helmbert

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 anyas return type).

使用这种表示法,您将返回的对象类型转换为 type AddTodoAction。但是,函数声明的返回类型仍然未定义(并且编译器将隐式假定any为返回类型)。

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 textproperty will generate the following (desired) error:

在这种情况下,省略必需的属性将产生预期的编译器错误。例如,省略该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"'.

Also see the playground example.

另请参阅游乐场示例

回答by azium

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}; };