【问题标题】:How to write function type definitions for anonymous functions in typescript?如何在打字稿中为匿名函数编写函数类型定义?
【发布时间】:2019-12-25 00:21:25
【问题描述】:

我在我的 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 => {
    ...
  }
}}

【问题讨论】:

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


    【解决方案1】:

    您应该能够使用contextual typing 为您推断参数类型,方法是让编译器意识到您需要Thunk 类型的值。由于我没有 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,而是一个更宽的 类型。将变量注释为比您分配给它的值更窄是错误的。

    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

    【讨论】:

    • 谢谢,先生,这两种解决方案都对我有用,第二个解决方案似乎有点垃圾时髦但没什么用,先生不那么安全意味着什么? (我是打字稿的新手)
    • 更新了关于如何不安全地使用类型断言的解释
    【解决方案2】:

    作为@jcalz 的第二个选项类型断言,现在最新的打字稿编译器警告这一点

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

    所以最好以这种方式使用它

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

    【讨论】:

    • .tsx 文件中禁止使用,一般情况下没有。
    猜你喜欢
    • 2022-11-26
    • 2023-01-17
    • 1970-01-01
    • 2021-07-12
    • 1970-01-01
    • 2018-06-26
    • 2018-12-27
    • 1970-01-01
    • 2021-12-15
    相关资源
    最近更新 更多