我创建了一个函数来记忆上下文值,并在React中将它们作为渲染props 返回,以避免在我不关心的值更改时重新渲染.(这很好用!)然而,我打字有困难.

目标是使子函数的类型与访问器的返回类型相同.

我遇到很多麻烦的部分是键入以下部分:

type ContextType = {
  state:{ a:number; b:number; }
  otherStuff:{ a:string; b:string }
}
export const ContextAccessor: <
  T extends {
    accessor: (ctx: ContextType) => ReturnType<T["accessor"]>;
    children: (ctx: ReturnType<T["accessor"]>) => JSX.Element;
  }
>(
  args: T
) => JSX.Element = ({ children, accessor }): JSX.Element =>

我的访问器函数被输入为accessor: (ctx: ContextType) => any,这使得函数children也有一个任意类型的输入参数.

我认为这是因为ReturnType<T["accessor"]>实际上不起作用

完整代码(无备忘录)如下:

type ContextType = {
  state:{ a:number; b:number; }
  otherStuff:{ a:string; b:string }
}
export const ContextAccessor: <
  T extends {
    accessor: (ctx: ContextType) => ReturnType<T["accessor"]>;
    children: (ctx: ReturnType<T["accessor"]>) => JSX.Element;
  }
>(
  args: T
) => JSX.Element = ({ children, accessor }): JSX.Element => {
  const { state, modifiers, accessors } = useMyContext();

  const accessed = useMemo(
    () => accessor({ state, modifiers, accessors }),
    [state, modifiers, accessors]
  );

  return children(accessed)

};


export const Test = () => {
  return (
    <ContextAccessor accessor={(ctx) => ctx.state.a}>
      {(transfer) => (
        <div>
          <div>{JSON.stringify(transfer)}</div>
        </div>
      )}
    </ContextAccessor>
  );
};

编辑我try 过的更多东西

我认为下面的方法不管用,因为ReturnType<Props<T>["accessor"]>被输入为未知,不是泛型.

type Props<T> = {
  accessor: (context: ContextType) => unknown;
  children: (ctx: ReturnType<Props<T>["accessor"]>) => JSX.Element;
};
export function StagingBuilderContext<T>(props: Props<T>): JSX.Element {

推荐答案

可以通过向accessor prop函数参数添加显式类型签名来实现:ctx~>;ctx: ContextType

export const Test = () => {
  return (
    <ContextAccessor accessor={(ctx: ContextType) => ctx.state.a}>
      {(transfer) => ( // inferred type for transfer is number
        <div>
          <div>{JSON.stringify(transfer)}</div>
        </div>
      )}
    </ContextAccessor>
  );
};

有了这个断言,accessor返回值立即可用,而不必从它的用法中推断出来,这样就可以对children进行正确的推断.我不完全确定是否要在accessor属性中使用ReturnType<T["accessor"]>,因为这指的是它本身,但它似乎确实正常工作.另一种方法是对返回类型使用类型参数.

TypeScript playground

Typescript相关问答推荐

等待的R没有用响应对象展开到R

ReturnType此索引方法与点表示法之间的差异

TypScript ' NoInfer '类型未按预期工作

使用Angular和API请求在CRUD操作后更新客户端数据的良好实践

找不到带名称的管道''

在键和值为ARGS的泛型函数中未正确推断类型

输入元素是类型变体的对象数组的正确方法是什么?'

ANGLE找不到辅助‘路由出口’的路由路径

如何在ANGLE中注册自定义验证器

(TypeScript)TypeError:无法读取未定义的属性(正在读取映射)"

为什么我在这个重载函数中需要`as any`?

ANGLE NumberValueAccessor表单控件值更改订阅两次

如何为特定参数定义子路由?

在抽象类构造函数中获取子类型

是否可以在类型脚本中定义条件返回类型,而不在函数体中使用类型转换?

必需的输入()参数仍然发出&没有初始值设定项&q;错误

如何为对象数组中的每个条目推断不同的泛型

React Context TypeScript错误:属性';firstName';在类型';iCards|iSearch';

类型分布在第一个泛型上,但不分布在第二个泛型上

在 TypeScript 中实现类型级别深度优先搜索