【问题标题】:Typescript generic parameter typing for curried function用于咖喱函数的打字稿通用参数类型
【发布时间】:2021-12-21 06:20:41
【问题描述】:

尝试键入一个柯里化函数,该函数首先接受一个函子,然后是一个对象

type TestType = {
  x: number;
  y: number;
  hello: string;
};

type CordinateType = {
  data: TestType;
  id: string;
};

const transform = <T extends object, K extends keyof T>(
  fntor: (val: T[K]) => any
) => (obj: T) =>
  Object.entries(obj).reduce((acc, [k, v]) => ({ ...acc, [k]: fntor(v) }), {});

const testData: CordinateType = {
  id: "uuid-222-uuid",
  data: {
    x: -3,
    y: 2,
    hello: "test"
  }
};

const positive = (x) => (Number.isInteger(x) ? Math.abs(x) : x);

const result = { ...testData, data: transform(positive)(testData) };
console.log("result", result);

Transform 是一个简单的函数,它接受函子并在对象上进行映射。

主要问题是 result.data 的类型是{},而应该是TestType

这是示例反应应用程序,setState 钩子函数无法推断出正确的类型

【问题讨论】:

    标签: typescript react-hooks functor currying generic-type-argument


    【解决方案1】:

    更新

    您可以传递通用参数之一 (T)。请注意,第二个参数需要使用默认值,因为我们要么让 typescript 找出参数,要么显式传递它们。

    import "./styles.css";
    import React, { useState, useCallback } from "react";
    
    type PointType = {
      x: number;
      y: number;
      comment: string;
    };
    
    type CordinateType = {
      data: PointType;
      id: string;
    };
    
    const transform = <T extends object, K extends keyof T = keyof T>(
      fntor: (val: T[K]) => any
    ) => (obj: T) =>
      Object.entries(obj).reduce(
        (acc, [k, v]) => ({ ...acc, [k]: fntor(v) }),
        {}
      ) as T;
    const positive = (x: any) => (Number.isInteger(x) ? Math.abs(x) : x);
    
    export default function App() {
      const [cordinate, setCordinate] = useState<CordinateType>({
        id: "uuid-xxx-uuid",
        data: {
          x: 1,
          y: -2,
          comment: "initial-point"
        }
      });
    
      const updateCoord = useCallback(() => {
        // setCordinate((old) => ({ ...old, data: old.data })); // this works type
        setCordinate((old) => ({
          ...old,
          data: transform<PointType>(positive)(old.data)
        }));
      }, []);
    
      return (
        <div className="App">
          <h1>Hello Cordinate</h1>
    
          <div>
            <pre>{JSON.stringify(cordinate.data)}</pre>
          </div>
    
          <button onClick={updateCoord}>Update</button>
        </div>
      );
    }
    


    fntor: (val: K) => K
    

    fntor 的类型不正确,因为val 不是对象的键,而是值之一。

    这里是固定代码:

    const transform = <T extends object, K extends keyof T>(
      fntor: (val: T[K]) => any
    ) => (obj: T) =>
      Object.entries(obj).reduce((acc, [k, v]) => ({ ...acc, [k]: fntor(v) }), {});
    
    const testData: Record<string, any> = {
      x: -3,
      y: 2,
      hello: "test"
    };
    
    const positive = (x: any) => (Number.isInteger(x) ? Math.abs(x) : x);
    
    const result = transform(positive)(testData);
    console.log("result", result);
    

    【讨论】:

    • 感谢 fntor 更新,我已进一步编辑问题,请检查
    • @vito 检查更新的答案
    • 还是不能取类型,请看第二个codepen链接
    • @vito 更新了你的反应代码并添加了它
    • 非常感谢,不理解= keyof T 部分,请添加一些解释,可能对其他人有帮助。可以避免类型转换transform&lt;PointType&gt;,它可以自动推断吗
    猜你喜欢
    • 1970-01-01
    • 2020-05-28
    • 2017-01-18
    • 1970-01-01
    • 2021-10-27
    • 2019-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多