如何用TypeScript泛型强耦合Grid与Grid.Item的Props类型?
实现Grid与Grid.Item的类型安全强耦合
要实现Grid的gridTemplateAreas和Grid.Item的gridArea强类型绑定,核心是从gridTemplateAreas字符串中提取合法的区域名称,再限制Grid.Item只能使用这些名称。以下是具体实现步骤:
1. 定义区域名称解析的类型工具
通过TypeScript模板字符串类型,从gridTemplateAreas格式的字符串中提取所有唯一的区域名称:
// 提取单个引号内的区域名称列表 type ExtractAreaNames<T extends string> = T extends `'${infer Content}'` ? Content extends `${infer Area} ${infer Rest}` ? Area | ExtractAreaNames<`'${Rest}'`> : Content : never; // 解析整个gridTemplateAreas字符串,去重后得到合法区域名称的联合类型 type ParseGridAreas<T extends string> = T extends `${infer FirstPart} ${infer Rest}` ? ExtractAreaNames<`'${FirstPart}'`> | ParseGridAreas<Rest> : ExtractAreaNames<`'${T}'`>;
2. 定义泛型组件Props
让GridProps成为泛型,接收区域名称的联合类型;GridItemProps则依赖这个联合类型,限制gridArea只能是其中的成员:
import React from 'react'; // Grid组件Props,泛型T是区域名称的联合类型 interface GridProps<T extends string> { gridTemplateAreas: T; children: React.ReactNode; } // Grid.Item组件Props,依赖Grid的区域类型T interface GridItemProps<T extends string> { gridArea: T; children: React.ReactNode; }
3. 实现泛型Grid组件
将Grid.Item作为Grid的静态属性,继承Grid的泛型参数,确保类型联动:
// 定义Grid组件,泛型T代表所有合法的区域名称 const Grid = <T extends string>(props: GridProps<T>) => { return ( <div style={{ display: 'grid', gridTemplateAreas: props.gridTemplateAreas }}> {props.children} </div> ); }; // 定义Grid.Item,复用Grid的泛型T,确保gridArea只能是T中的成员 Grid.Item = <T extends string>(props: GridItemProps<T>) => { return <div style={{ gridArea: props.gridArea }}>{props.children}</div>; };
4. 使用示例与类型校验
使用时,TypeScript会自动从gridTemplateAreas中推导合法的区域名称,若Grid.Item使用了不存在的名称会直接报错:
// 正确用法,所有gridArea都在gridTemplateAreas中定义 <Grid gridTemplateAreas="'item1 item2' 'item3 item3'"> <Grid.Item gridArea="item1">1st item of grid</Grid.Item> <Grid.Item gridArea="item2">2nd item of grid</Grid.Item> <Grid.Item gridArea="item3">3rd item of grid</Grid.Item> </Grid> // 错误用法:TypeScript会报错,因为"item4"不在gridTemplateAreas的定义中 <Grid gridTemplateAreas="'item1 item2'"> <Grid.Item gridArea="item4">Invalid item</Grid.Item> </Grid>
补充说明
- 上述类型工具支持标准的
gridTemplateAreas格式(用单引号包裹行,空格分隔列); - 若需要支持无引号的简化格式,可以调整
ExtractAreaNames的匹配逻辑; - 泛型推导是自动完成的,无需手动传入类型参数,使用体验和普通组件一致。
内容的提问来源于stack exchange,提问作者Vishal
相关产品推荐
相关产品推荐

