如何根据参数为函数返回值定义对应数量元素的类型?
为动态生成键的异步函数定义返回类型
对于你提供的createItems函数,我们可以通过TypeScript的模板字面量类型和映射类型来定义返回值类型,根据传入的nb参数是否为字面量类型,有两种实现方案:
方案一:精确类型(适用于nb为字面量的场景)
当你传入明确的数字字面量(比如3)时,TypeScript可以推断出返回对象包含的所有键,实现步骤如下:
- 定义生成1到N数字范围的类型:
type NumberRange<N extends number, Acc extends number[] = []> = Acc['length'] extends N ? Acc[number] : NumberRange<N, [...Acc, Acc['length'] + 1]>;
- 将数字转换为带前导零的两位字符串,生成
item01、item02这类键类型:
type ItemKey<Num extends number> = `item${Num extends 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ? `0${Num}` : `${Num}`}`;
- 生成对应键的对象类型:
type ItemsObject<N extends number> = { [K in ItemKey<NumberRange<N>>]: Item; };
- 修改函数的类型定义,使其接受泛型参数并返回精确类型:
async function createItems<N extends number>(nb: N = 10 as N): Promise<ItemsObject<N>> { const items: Item[] = await Promise.all( Array.from({ length: nb }, (_, idx) => createItem(idx + 1)) ); return items.reduce( (acc, item, idx) => { const num = String(idx + 1).padStart(2, '0'); acc[`item${num}` as ItemKey<NumberRange<N>>] = item; return acc; }, {} as ItemsObject<N>, ); }
此时调用createItems(3),TypeScript会自动识别返回对象包含item01、item02、item03三个键,解构时能获得完整的类型提示。
方案二:宽泛类型(适用于nb为动态值的场景)
如果nb是动态的变量而非字面量,或可能的取值范围很大(超过TypeScript递归类型的限制),可以定义一个更宽泛的类型来保证类型安全:
type ItemsObject = { [key: `item${string}`]: Item; }; async function createItems(nb = 10): Promise<ItemsObject> { const items: Item[] = await Promise.all( Array.from({ length: nb }, (_, idx) => createItem(idx + 1)) ); return items.reduce( (acc, item, idx) => { const num = String(idx + 1).padStart(2, '0'); acc[`item${num}`] = item; return acc; }, {} as ItemsObject, ); }
这个类型允许所有以item开头的键对应Item类型,虽然没有精确的键名提示,但依然能避免错误的键访问或类型不匹配问题。
内容的提问来源于stack exchange,提问作者Martial
相关产品推荐
相关产品推荐

