const list = ['rabbits', 'raccoons', 'reindeer', 'red pandas'] as const
const filteredList = list.filter(e => e.includes('re'))
如何输入
filteredList
?我想到了 (typeof list[number])[]
,TS 对此也没什么问题,但由于 list[number]
只是一个项目,所以对我来说,该类型更像是一个包含重复项目的数组,例如['reindeer', 'reindeer']
或['red pandas', 'red pandas']
。不知道这样说是否正确?
实际上 TypeScript 将
filteredList
推断为 ("rabbits" | "raccoons" | "reindeer" | "red pandas")[]
类型,它等于 (typeof list[number])[]
,我认为完全可以这样做。
如果您想要在
filteredList
上获得最准确的类型,您可以使用自定义帮助器类型,在编译时过滤 typeof list
。然后 assert filteredList
到该类型。我想出了这个灵感来自@jcalz关于可变元组类型的这个答案。
本质上,您检查
list
中的项目是否可分配给 ${string}${U}${string}
,其中 U
是您的过滤条件(例如 "re"
)。如果是这样,该项目将保留在生成的元组类型中。如果没有,则将其删除。
type FilterTuple<
T extends readonly any[],
U extends string,
> = T extends readonly [infer F, ...infer R]
? [F] extends [`${string}${U}${string}`]
? [F, ...FilterTuple<R, U>]
: FilterTuple<R, U>
: [];
const list = ["rabbits", "raccoons", "reindeer", "red pandas"] as const;
const filteredList = list.filter((e) => e.includes("re")) as FilterTuple<
typeof list,
"re"
>;
// const filteredList: ["reindeer", "red pandas"]