【问题标题】:Using Typescript generics in a callback invoking a React useState setter在调用 React useState setter 的回调中使用 Typescript 泛型
【发布时间】:2022-01-11 16:00:46
【问题描述】:

根据Typescript,这段代码有如下问题:Argument of type 'number' is not assignable to parameter of type 'SetStateAction<T>'.ts(2345)

使用类型或类型联合代替泛型的类似版本将起作用(实际上,可能会建议使用具有所有预期类型的​​联合)。

不过,如果我想坚持使用泛型,我将如何修改此代码以使其被接受?

import React, { Dispatch, SetStateAction, useState } from 'react';

function useValue<T>(init: T) {
  return useState<T>(init);
}

function SpecialButton<T>({
  value,
  setValue,
}: {
  value: T;
  setValue: Dispatch<SetStateAction<T>>;
}) {
  switch (typeof value) {
    case 'number':
      return <button onClick={() => setValue(value + 1)}>Add 1 to {value}</button>;
    default:
      return <div>UNSUPPORTED</div>;
  }
}

function App() {
  const [value, setValue] = useValue<number>(0);
  return <SpecialButton value={value} setValue={setValue} />;
}

(另外,我注意到在类型等于数字的情况下,值将被转换为T | number,但我不知道如何利用它)。

【问题讨论】:

    标签: reactjs typescript generics typescript-generics react-typescript


    【解决方案1】:

    我可以建议你下一个缩小类型的方法:

    function useValue<T>(init: T) {
      return useState<T>(init);
    }
    
    type Parameters<T> = {
      value: T;
      setValue: Dispatch<SetStateAction<T>>;
    };
    
    const isNumberParams = (parameters: { value: unknown }): parameters is Parameters<number> =>
      typeof parameters.value === 'number';
    
    const isStringParams = (parameters: { value: unknown }): parameters is Parameters<string> =>
      typeof parameters.value === 'string';
    
    function SpecialButton<T>(params: Parameters<T>) {
      if (isNumberParams(params)) {
        return (
          <button onClick={() => params.setValue(params.value + 1)}>Add 1 to {params.value}</button>
        );
      }
      if (isStringParams(params)) {
        return (
          <button onClick={() => params.setValue(params.value + '1')}>Add 1 to {params.value}</button>
        );
      }
      return <div>UNSUPPORTED</div>;
    }
    
    function App() {
      const [value, setValue] = useValue<number>(0);
      return <SpecialButton value={value} setValue={setValue} />;
    }
    

    【讨论】:

    • 我发现缩小类型会以某种方式相关,但我不知道如何实现它。 is 关键字模式仍然感觉有点奇怪,但它似乎很有用(不完全确定我是否更喜欢联合而不是这个)。
    【解决方案2】:

    我会尝试像这样声明一个自定义类型:

    import React, { Dispatch, SetStateAction, useState } from 'react'  
    
    // Declare custom Type:
    type StateActionType<T> = SetStateAction<T>
    

    然后你用它SpecialButton声明:

    // Use the custom Type:
    function SpecialButton<T>({ value, setValue } : {
        value: T,
        setValue: Dispatch<StateActionType<T>>
    }) {
    

    【讨论】:

    • 对我来说这仍然产生Argument of type 'number' is not assignable to parameter of type 'StateActionType&lt;T&gt;'.ts(2345)
    猜你喜欢
    • 2021-04-03
    • 1970-01-01
    • 2021-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-02
    相关资源
    最近更新 更多