简体   繁体   English

如何在打字稿中为匿名函数编写函数类型定义?

[英]How to write function type definitions for anonymous functions in typescript?

I am using redux-thunk in my react-native(typescript) redux project.我在我的 react-native(typescript) redux 项目中使用 redux-thunk。 And I am using thunkWithExtraArgument Helper to provide the reference of my apollo client variable and since I get three-argument for the return function that is我使用 thunkWithExtraArgument Helper 来提供我的 apollo 客户端变量的引用,因为我得到了返回函数的三个参数

...
return async (dispatch, getState, client) => 
...
// and with typescript
import { NormalizedCacheObject } from 'apollo-cache-inmemory'
import ApolloClient from 'apollo-client'
import { Dispatch } from 'redux'

import { ReduxStore } from '../interfaces/redux.ts';

...
return async (dispatch: Dispatch, getState: () => ReduxStore, client: ApolloClient<NormalizedCacheObject>): Promise<void>) => {
...
}

that I have to type a lot of code already everywhere so is there any solution to this.我必须在任何地方输入大量代码,所以有什么解决方案吗?

Currently, I am doing is this:目前,我正在做的是:


import { NormalizedCacheObject } from 'apollo-cache-inmemory'
import ApolloClient from 'apollo-client'
import { Dispatch } from 'redux'
import { ReduxStore } from '../interfaces/redux.ts'

// actually i outsources both GetState and Client types
type GetState = () => ReduxStore
// where ReduxStore is custom defined interface
type Client = ApolloClient<NormalizedCacheObject>

const fetchSomeData = (id: string) => {
  return async (dispatch: Dispatch, getState: GetState, client: Client): Promise<void>) => {
    ...
  }
}

What I tried and need is that我尝试和需要的是

...
export type Thunk = (dispatch: Dispatch, getState: () => ReduxStore, client: ApolloClient<NormalizedCacheObject>): Promise<void>
...

// action creator

const fethcSomeData = (id: string) => {
  return async (dispatch, getState, client): Thunk => {
    ...
  }
}}

You should be able to use contextual typing to infer the parameter types for you, by having the compiler realize that you want a value of type Thunk .通过让编译器意识到您需要Thunk类型的值,您应该能够使用上下文类型为您推断参数类型。 Since I don't have react/redux typings (and the question is really about the general issue I think) I will use something made up:由于我没有 react/redux 类型(并且问题实际上是关于我认为的一般问题)我将使用一些组成的内容:

type Spronk = (x: string, y: number, z: boolean) => Promise<string>;

The most type-safe way is to annotate a variable of this type and return it:最类型安全的方法是注释这种类型的变量并返回它:

const fethcSomeData = (id: string) => {
  const ret: Spronk = async (x, y, z) => (z ? x : y.toFixed());
  return ret;
};

Or you could use a type assertion which is more terse but a bit less safe (it will let you narrow the value):或者您可以使用更简洁但安全性稍差的类型断言(它可以让您缩小值):

const fthecSomeData = (id: string) => {
  return <Spronk>(async (x, y, z) => (z ? x : y.toFixed())); 
};

Either way should hopefully work for you.无论哪种方式都应该对你有用。 Good luck!祝你好运!


UPDATE: Here's what I mean by unsafe.更新:这就是我所说的不安全的意思。 The following is an error:以下是一个错误:

const errorCaught: Spronk = async (x, y, z) => (z ? x : y); // error!
// (string | number) is not assignable to string

I've annotated the type of errorCaught to be Spronk .我已经注释类型errorCaughtSpronk The compiler recognizes that I am returning a string | number编译器识别出我正在返回一个string | number string | number instead of a string , meaning that errorCaught is not a true Spronk , but a wider type. string | number ,而不是一个string ,这意味着errorCaught不是真正Spronk ,但更宽的类型。 It is an error to annotate a variable to be narrower than the value you assign to it.将变量注释为比分配给它的值更窄是错误的。

const errorSuppressed = <Spronk>(async (x, y, z) => (z ? x : y)); // no error

Here, I've asserted the type of errorCaught to be Spronk .在这里,我断言类型errorCaughtSpronk The compiler still recognizes that the value is wider than a Spronk , but type assertions specifically allow you to say that a value is of a narrower type than the compiler can verify.编译器仍然识别出该值比Spronk ,但类型断言特别允许您说值的类型比编译器可以验证的类型更窄。 There are times when such flexibility is useful, but it is dangerous.有时这种灵活性很有用,但也很危险。 In the case of errorSuppressed we've deliberately lied to the compiler, which can get us in trouble at runtime:errorSuppressed的情况下,我们故意向编译器撒谎,这可能会在运行时给我们带来麻烦:

errorSuppressed("a", 1, false).then(s => console.log(s.charAt(0))); // compiles, but
// at runtime: "TypeError, s.charAt is not a function"

Hope that makes sense.希望这是有道理的。

Link to code 代码链接

As @jcalz's second option type assertion now the latest typescript compiler warns about this as作为@jcalz 的第二个选项类型断言,现在最新的打字稿编译器对此发出警告

Type assertion using the '<>' syntax is forbidden. Use the 'as' syntax instead

so using it this way is preferable所以以这种方式使用它是可取的


const fetchSomeData = (id: string) => {
  return <Spronk>(async (x, y, z) => (z ? x : y.toFixed())); 
};

to

const fetchSomeData = (id: string) => {
  return (async (x, y, z) => (z ? x : y.toFixed())) as Spronk; 
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM