ts 字符串模板类型 案例

原创
09/13 17:27
阅读数 149

url解析

https://blog.gplane.win/posts/url-parser-with-template-string-types.html

type ParseProtocol<I, AST> =
    I extends `${infer P}://${infer Rest}` ? [AST & { protocol: P }, Rest] : never

type ParseAuth<I, AST> =
    I extends `${infer A}@${infer Rest}` ?
    A extends `${infer U}:${infer P}` ? [AST & { username: U, password: P }, Rest] :
    [AST & { username: A }, Rest] : [AST, I]

type ParseHost<I, AST> =
    I extends `${infer H}/${infer Rest}` ?
    H extends `${infer Name}:${infer Port}` ?
    ParsePort<Port> extends never ? never :
    ParsePort<Port> extends infer Port ?
    [AST & { hostname: Name, port: Port }, Rest] :
    [AST & { hostname: H }, Rest] :
    never : never
type Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
type ParsePort<I, O extends string = ''> =
    I extends '' ? O :
    I extends `${Digit}${infer Rest}` ?
    I extends `${infer Char}${Rest}` ?
    ParsePort<Rest, `${O}${Char}`> :
    never : never

type ParsePathname<I, AST> =
    I extends `${infer P}?${infer Rest}` ? [AST & { pathname: `/${P}` }, `?${Rest}`] :
    I extends `${infer P}#${infer Rest}` ? [AST & { pathname: `/${P}` }, `#${Rest}`] :
    I extends `${infer P}` ? [AST & { pathname: `/${P}` }, ''] : never

type ParseQuery<I, AST> =
    I extends `?${infer Q}#${infer Rest}` ? [AST & { query: ParseQueryItems<Q> }, `#${Rest}`] :
    I extends `?${infer Q}` ? [AST & { query: ParseQueryItems<Q> }, ''] : [AST, I]
type ParseQueryItems<I> =
    string extends I ? [] :
    I extends '' ? [] :
    I extends `${infer K}=${infer V}&${infer Rest}` ? [{ key: K, value: V }, ...ParseQueryItems<Rest>] :
    I extends `${infer K}&${infer Rest}` ? [{ key: K, value: null }, ...ParseQueryItems<Rest>] :
    I extends `${infer K}=${infer V}` ? [{ key: K, value: V }] :
    I extends `${infer K}` ? [{ key: K, value: null }] : []

type ParseHash<I, AST> =
    I extends `#${infer H}` ? [AST & { hash: `#${H}` }] : [AST]

type ParseURL<I extends string> =
    ParseProtocol<I, {}> extends [infer AST, infer Rest] ?
    ParseAuth<Rest, AST> extends [infer AST, infer Rest] ?
    ParseHost<Rest, AST> extends [infer AST, infer Rest] ?
    ParsePathname<Rest, AST> extends [infer AST, infer Rest] ?
    ParseQuery<Rest, AST> extends [infer AST, infer Rest] ?
    ParseHash<Rest, AST> extends [infer AST] ? AST :
    never : never : never : never : never : never

type Merge<T> = { [P in keyof T as T[P] extends '' ? never : P]: T[P] }

type Result = Merge<ParseURL<'https://username:password@example.com:443/p/a/t/h?k1=v1&k2=v2#h'>>
/*
type Result = {
    protocol: "https";
    username: "username";
    password: "password";
    hostname: "example.com";
    port: "443";
    pathname: "/p/a/t/h";
    query: [{
        key: "k1";
        value: "v1";
    }, {
        key: "k2";
        value: "v2";
    }];
    hash: "#h";
}

*/

vuex action 提示

https://segmentfault.com/a/1190000023931783

type GetMutations<Module> = Module extends { mutations: infer M } ? M : never

type AddPrefix<Prefix, Keys> = `${Prefix & string}/${Keys & string}`

type GetSubModuleKeys<Module, Key> = Module extends { modules: infer SubModules }
   ? AddPrefix<Key, GetModulesMutationKeys<SubModules>>
   : never

type GetModuleMutationKeys<Module, Key> = AddPrefix<Key, keyof GetMutations<Module>> | GetSubModuleKeys<Module, Key>

type GetModulesMutationKeys<Modules> = {
   [K in keyof Modules]: GetModuleMutationKeys<Modules[K], K>
}[keyof Modules]

type Action<Mutations, Modules> = keyof Mutations | GetModulesMutationKeys<Modules>

type Store<Mutations, Modules> = {
   dispatch(action: Action<Mutations, Modules>): void
}

type VuexOptions<Mutations, Modules> = {
   mutations: Mutations,
   modules: Modules
}

declare function Vuex<Mutations, Modules>(options: VuexOptions<Mutations, Modules>): Store<Mutations, Modules>

const store = Vuex({
   mutations: {
      root() { },
   },
   modules: {
      cart: {
         mutations: {
            add() { },
            remove() { }
         }
      },
      user: {
         mutations: {
            login() { }
         },
         modules: {
            admin: {
               mutations: {
                  login() { }
               },
            }
         }
      }
   }
})

store.dispatch("root")
store.dispatch("cart/add")
store.dispatch("user/login")
store.dispatch("user")

ast, 居然用ts写了表达式计算

https://github.com/microsoft/TypeScript/pull/40336#issuecomment-684784211

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部