我很难理解如何创建通用上下文. 基本上我想要的是能够将一个值传递给Root,然后让子元素们推断正确的类型,这可能吗?我知道这很有可能,因为TabHeaderPropsTabContextPropsTabRootProps之间没有联系.

这是一个可行的简化版本,但它比我希望的更冗长.

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

type Headers = 'Foo' | 'Bar' | 'Baz';
const defaultValue: Headers = 'Foo';

type TabsContextProps<T = any> = {
  activeTab: T;
  setActiveTab: Dispatch<SetStateAction<T | undefined>>;
};

const TabsContext = React.createContext<TabsContextProps | undefined>(
  undefined,
);

type TabsRootProps<T> = {
  defaultValue: T;
  children: React.ReactNode;
};

export function TabsRoot<T>({ children }: TabsRootProps<T>) {
  const [activeTab, setActiveTab] = useState<T>();

  return (
    <TabsContext.Provider
      value={{
        setActiveTab,
        activeTab,
      }}
    >
      {children}
    </TabsContext.Provider>
  );
}

function useTabsRootContext<T>(): TabsContextProps<T> {
  if (!React.useContext(TabsContext)) {
    throw new Error('useTabsRootContext must be used inside TabsRoot');
  }
  return React.useContext(TabsContext) as TabsContextProps<T>;
}

type TabHeaderProps<T> = {
  value: T;
};

const TabsHeader = <T,>({ value }: TabHeaderProps<T>) => {
  const { activeTab } = useTabsRootContext<T>();
  if (!activeTab !== value) {
    return null;
  }
  return <p>Im Active</p>;
};

const Tabs = () => {
  <TabsRoot<Headers> defaultValue={defaultValue}>
    <TabsHeader<Headers> value="Baz" /> {/* This work but i preferably want this to be infered based on the TabsRootType */}
  </TabsRoot>;
};

理想情况下我希望拥有它:

const Tabs = () => {
  <TabsRoot defaultValue={defaultValue}>
    <TabsHeader value="Baz" />
    <TabsHeader value="error" /> {/* I want this to throw an error */}
  </TabsRoot>;
};

推荐答案

不幸的是,这确实是不可能的:

  • 除了通过它们的props 和上下文之外,React组件实例对其父组件一无所知.就您的情况而言,您没有通过props 建立明确的联系,而只是通过上下文建立联系
  • 但TypScript通用类型参数推断仅与函数调用或类构造函数的参数一起发生(也适用于React组件实例props ).因此React上下文无法影响类型推断

Typescript相关问答推荐

创建一个通用上下文,允许正确推断其中的子项

需要使用相同组件重新加载路由变更数据—React TSX

类型{...}的TypeScript参数不能赋给类型为never的参数''

如何将联合文字类型限制为文字类型之一

如何为父类构造函数中的修饰属性赋值?

根据上一个参数值查找参数类型,也返回类型

将对象属性转换为InstanceType或原样的强类型方法

对于合并对象中的可选属性(例如选项),类型推断可能是错误的

如何将泛型对象作为返回类型添加到类型脚本中

诡异的文字类型--S为物语的关键

记录键的泛型类型

如何在Reaction Query Builder中添加其他字段?

以Angular 执行其他组件的函数

如何从一个泛型类型推断多个类型

如何通过属性名在两个泛型数组中找到匹配的对象?

在Reaction中折叠手风琴

声明遵循映射类型的接口

创建一个函数,该函数返回一个行为方式与传入函数相同的函数

对于VUE3,错误XX不存在于从不存在的类型上意味着什么?

必须从注入上下文调用Angular ResolveFn-inject()