You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Context Provider中如何基于propProvide的keyof定义propData类型?

解决方案

1. 定义带泛型的Provider与Context

通过泛型捕获propProvide的结构,让Context能携带该结构的类型信息:

import { createContext, useContext, ReactNode } from 'react';

// Provider的props类型,泛型T约束propProvide的结构
type MyComponentProviderProps<T extends Record<string, unknown>> = {
  propProvide: T;
  children: ReactNode;
};

// 创建泛型Context,初始值设为null
const MyComponentContext = createContext<Record<string, unknown> | null>(null);

// 实现Provider组件,用泛型T保留propProvide的类型信息
function MyComponentProvider<T extends Record<string, unknown>>({
  propProvide,
  children,
}: MyComponentProviderProps<T>) {
  return (
    <MyComponentContext.Provider value={propProvide}>
      {children}
    </MyComponentContext.Provider>
  );
}

2. 定义空格分隔的Key类型工具

创建递归类型,确保propData只能是propProvide的key以空格分隔的组合:

// 生成允许空格分隔的key组合类型
type SpaceSeparatedKeys<T extends string> = T | `${T} ${SpaceSeparatedKeys<T>}`;

3. 实现类型约束的ComponentChild

让子组件关联Context的类型,同时限制propData为合法的空格分隔key:

// 子组件props类型,泛型T关联Provider中propProvide的结构
type ComponentChildProps<T extends Record<string, unknown>> = {
  propData: SpaceSeparatedKeys<keyof T & string>;
};

function ComponentChild<T extends Record<string, unknown>>({
  propData,
}: ComponentChildProps<T>) {
  // 断言Context值为T类型(确保在Provider内部使用)
  const contextData = useContext(MyComponentContext) as T;
  
  // 分割propData获取对应值示例
  const targetValues = propData.split(' ').map(key => contextData[key]);
  
  return <div>{targetValues.join(', ')}</div>;
}

4. 使用示例

此时TypeScript会自动校验propData的合法性,传入不存在的key会直接报错:

<MyComponentProvider
  propProvide={{
    dataA: "10",
    dataB: "20"
  }}
>
  {/* 合法:仅允许propProvide的key以空格分隔 */}
  <ComponentChild propData="dataA dataB" />
  
  {/* 非法:TypeScript会提示类型错误 */}
  {/* <ComponentChild propData="dataC" /> */}
</MyComponentProvider>

内容的提问来源于stack exchange,提问作者Hai Tien

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 20:35:03