原文链接: ts 字符串模板类型 lodash get函数的类型推断和vuex 合法的 action
上一篇: useContext更佳实践 代码
下一篇: ts 字符串模板类型 案例
TypeScript 4.1 新特性:字符串模板类型,Vuex 终于有救了?
联合类型在展开时会进行排列组合
type T0 = `${'top' | 'bottom'}-${'left' | 'right'}`;
// type T0 = "top-left" | "top-right" | "bottom-left" | "bottom-right"
有了四个关键字方便开发, 不知道后面会不会有驼峰转换的
大写, 小写, 首字母大写, 首字母小写
type T1<T extends string> = `${uppercase T} ${lowercase T} ${capitalize T} ${uncapitalize T} `
type T2 = T1<'heLLo'>
// type T2 = "HELLO hello HeLLo heLLo "
type T3 = T1<'HeLLo'>
// type T3 = "HELLO hello HeLLo heLLo "
配合infer实现类似正则表达式提取
type Pointer<S extends string> = S extends `[${infer X}-${infer Y}]` ? {x:X,y:Y} : unknown
type T4 = Pointer<'[1-2]'>
/**
type T4 = {
x: "1";
y: "2";
}
*/
type T5 = Pointer<'[abc-efd]'>
/**
type T5 = {
x: "abc";
y: "efd";
}
*/
配合拓展运算符和unfer递归实现列表的join
type List = (string | number | boolean | bigint)[]
type Join<T extends List, C extends string> = T extends [] ? '' :
T extends [unknown] ? `${T[0]}` :
T extends [unknown, ...infer U] ? `${T[0]}${C}${Join<U, C>}` : string
type T1 = Join<[1, 2, 3], '-'>
// type T1 = "1-2-3"
type T2 = Join<['a', 'b', 'c'], ','>
// type T2 = "a,b,c"
type T3 = Join<['a', 1, 3], '='>
// type T3 = "a=1=3"
匹配策略
两个infer不相邻的话是贪婪模式
type T4<S extends string> = S extends `${infer T}x` ? T : unknown
type T5 = T4<'abcdx'>
// type T5 = "abcd"
type T6 = T4<'abcdxxxx'>
// type T6 = "abcdxxx"
两个infer相邻的话, 第一个只会匹配到第一个字符
type T1<S extends string> = S extends `${infer X}${infer Y}` ? [X,Y] : unknown
type T2 = T1<'abcd'>
// type T2 = ["a", "bcd"]
lodash get函数的类型, 支持任意路径的属性类型推断
type PropType<T, Path extends string> =
string extends Path ? unknown :
Path extends keyof T ? T[Path] :
Path extends `${infer K}.${infer R}` ? K extends keyof T ? PropType<T[K], R> : unknown : unknown
declare function get<T, P extends string>(obj: T, path: P): PropType<T, P>
const stu = {
name: 'ace',
age: 18,
class: {
name: 'class name',
teacher: {
name: 'tea',
id: 1234
}
}
}
const v0 = get(stu, 'age')
// const v0: number
const v1 = get(stu, 'class.aa')
// const v1: unknown
const v2 = get(stu, 'class.teacher.id')
// const v2: number
const v3 = get(stu, 'class.teacher')
/**
const v3: {
name: string;
id: number;
}
*/
为vuex的dispatch加类型, 不过一般好像都是直接 将字面量转成字符串常量使用的,
type VuexOptions<M, N> = {
namespace?: N,
mutations: M,
}
type Action<M, N> = N extends string ? `${N}/${keyof M & string}` : keyof M
type Store<M, N> = {
dispatch(action: Action<M, N>): void
}
declare function Vuex<M, N>(options: VuexOptions<M, N>): Store<M, N>
const store = Vuex({
namespace: "cart" as const,
mutations: {
add() { },
remove() { }
}
})
store.dispatch("cart/add")
store.dispatch("cart/remove")
store.dispatch("cart/add2")