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

时间:2019-08-19 18:59:34

标签: reactjs typescript redux react-redux redux-thunk

我在我的react-native(typescript)redux项目中使用redux-thunk。而且我正在使用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>) => {
...
}

我必须到处都键入很多代码,所以对此有任何解决方案。

当前,我正在这样做:


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>) => {
    ...
  }
}

我想做的是

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

// action creator

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

2 个答案:

答案 0 :(得分:2)

通过使编译器认识到您想要类型为Thunk的值,您应该能够使用contextual typing为您推断参数类型。由于我没有react / redux类型(问题实际上是我认为的一般性问题),因此我将使用一些组合而成的东西:

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

最安全的方式是注释此类型的变量并将其返回:

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

或者您可以使用type assertion,它更简洁但安全性稍差(它将使您缩小值):

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

这两种方法都有望为您服务。祝你好运!


更新:这就是我所说的不安全。以下是错误:

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

我已注释 errorCaught的类型为Spronk。编译器认识到我返回的是string | number而不是string,这意味着errorCaught不是真正的Spronk,而是 wide 类型。将变量注释为比您为其分配的值窄的错误。

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

在这里,我断言了 errorCaught的类型为Spronk。编译器仍然认识到该值比Spronk宽,但是类型断言明确允许您说一个值的类型比编译器可以验证的窄。有时候,这种灵活性很有用,但很危险。在errorSuppressed的情况下,我们故意欺骗了编译器,这可能会在运行时给我们带来麻烦:

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

希望如此。

Link to code

答案 1 :(得分:0)

作为@jcalz的第二种类型声明,现在最新的打字稿编译器对此警告为

setOnCheckedChangeListener()

因此最好以这种方式使用

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