假设我有这样的类型:
type SegmentBase = string;
type ParamSegment = `:${string}`;
type Segment = SegmentBase | ParamSegment;
type Path = `${Segment}/${Segment}`;现在是否可以构造一个类型Extractor<T extends Path>,以下列方式提取ParamSegment的${string}部分:
Extractor<'foo/:bar'>
// turns into
{
bar: string;
}Extractor<':foo/:bar'>
// turns into
{
foo: string;
bar: string;
}Extractor<'foo/bar'>
// turns into
{}发布于 2022-05-21 17:40:30
您需要为此创建一个递归辅助类型。
首先,创建与参数名称匹配的类型。
type _UnwrapParam<P extends string, S extends string[]> = P extends `:${infer Q}` ? [Q, ...S] : S;
type _Match<T extends string, S extends string[]> = T extends `${infer P}/${infer R}`
? [...UnwrapParam<P, S>, ..._Match<R, S>]
: _UnwrapParam<T, S>
export type Match<T extends string> = _Match<T, []>[number];那你就可以
export type Extractor<T extends string> = {
[K in Match<T>]: string;
};编辑:,既然类型为4.5,最好按下面的方式实现_Match类型,这样它就可以从尾递归消除中受益。
type _Match<
T extends string,
S extends string[]
> = T extends `${infer P}/${infer R}`
? _Match<R, _UnwrapParam<P, S>>
: _UnwrapParam<T, S>;发布于 2022-05-21 17:28:42
我想你需要这样的东西:
type Extractor<S extends string> =
S extends `${infer L}/${infer R}`
? {
[K in L | R as K extends `:${infer Key}` ? Key : never]: string
}
: never一些测试用例:
type T1 = Extractor<'foo/:bar'>
// type T1 = {
// bar: string;
// }
type T2 = Extractor<':foo/:bar'>
// type T2 = {
// foo: string;
// bar: string;
// }
type T3 = Extractor<'foo/bar'>
// type T3 = {}如果不适合您的用例,请添加更多的测试用例。
https://stackoverflow.com/questions/72331640
复制相似问题