如何编写类型安全的React组件数组及函数元组的TypeScript定义?
类型安全的组件-Props配对与函数参数匹配实现
React组件场景
要让TypeScript确保数组中每个[组件, Props]元组的Props与组件的props类型严格匹配,你可以通过泛型约束和条件类型实现类型安全的数组定义与函数签名:
类型安全的渲染函数
import React, { ComponentType, ReactElement } from 'react'; function renderComponents<T extends readonly [ComponentType<any>, any][]>( components: { [K in keyof T]: T[K] extends [ComponentType<infer P>, infer ProvidedProps] ? ProvidedProps extends P ? T[K] : never : never } ): ReactElement[] { return components.map(([Comp, props]) => <Comp {...props} />); }
使用示例
// 定义示例组件 const Button: ComponentType<{ label: string; onClick?: () => void }> = ({ label, onClick }) => ( <button onClick={onClick}>{label}</button> ); const Text: ComponentType<{ content: string }> = ({ content }) => <p>{content}</p>; // ✅ 合法调用:Props与组件要求完全匹配 renderComponents([ [Button, { label: "点击我" }], [Text, { content: "Hello World" }] ]); // ❌ 类型报错:Button的props缺少label,多余content renderComponents([ [Button, { content: "错误属性" }] ]);
通用函数场景(本质问题)
如果是通用的[函数, 参数数组]配对需求,同样可以用类似的泛型约束实现类型安全:
类型安全的执行函数
function executeFunctions<T extends readonly [(...args: any[]) => any, any][]>( functions: { [K in keyof T]: T[K] extends [(...args: infer Args) => infer _R, infer ProvidedArgs] ? ProvidedArgs extends Args ? T[K] : never : never } ): ReturnType<T[number][0]>[] { return functions.map(([fn, args]) => fn(...args)); }
使用示例
// 定义示例函数 function add(a: number, b: number): number { return a + b; } function greet(name: string): string { return `你好,${name}`; } // ✅ 合法调用:参数与函数入参类型匹配 executeFunctions([ [add, [1, 2]], [greet, ["Alice"]] ]); // ❌ 类型报错:add要求number类型参数,传入了string executeFunctions([ [add, ["1", "2"]] ]);
核心原理
通过TypeScript的infer关键字提取组件的props类型或函数的参数类型,再利用映射类型遍历数组的每个元组,用extends检查传入的参数是否与提取出的类型匹配。如果不匹配,该元组的类型会被推断为never,触发TypeScript的类型错误,从而强制保证每个元组的函数与参数配对正确。
内容的提问来源于stack exchange,提问作者Dima Vishnyakov
相关产品推荐
相关产品推荐

