/**
* 简单系统类型
*/
// 1.变量 函数 类等都可以类型声明,编译器会基于声明的类型做检查,类型不匹配是会报错
// 1.1 比如一个add函数既可以做整数加法也可以做浮点数加法,却需要声明两个函数,(个人理解是java中的写法)
int add(int a, int b){
return a + b;
}
double add(double a, double b){
return a + b;
}
// 1.2 如果类型能传参数就好了,传入int就是整数加法,传入dobule就是浮点数加法,于是就有了第二种类型系统
/**
* 支持泛型的类型系统
*/
// 1. 含义: 泛型的英文是 Generic Type,通用的类型,它可以代表任何一种类型,也叫类型参数
// 2.上面的add函数有了类型可以这样写
T add<T>(T a, T b){
return a + b
}
add(1, 2)
add(1.111, 2.2222)
// 3.声明时会把变化的类型声明成泛型(类型参数),在调用时在确定类型
// 4.如果是一个返回对象某个属性值的函数,类型该怎么写呢?
function getPropValue<T>(obj: T, key): key对应的属性值类型 {
return obj[key]
}
// 5.好像拿到了T, 也不能拿到它的属性和属性值,如果能对类型参数T做一些逻辑处理就好了,所以就有了第三种类型系统
/**
* 支持类型变成的类型系统
* 在Java理,拿到了对象类型就能找到它的类,进一步拿到各种信息,所以类型系统支出泛型就够了
* 但在JavaScript里面,对象可以字面量类型的方式创建,还可以灵活的增删属性,拿到对象并不能确定什么,所以要支持对传入的类型参数做进一步的处理
* 对传入的类型参数(泛型)做各种逻辑运算,产生新的类型,这就是类型编程
*/
// 1.上面的getPropValue 可以这么写
// 这里的keyof T, T[Key]就是对类型参数T做了运算
// 2. TypeScript的类型系统就是第三种,支持对类型参数做各种逻辑处理,可以写很复杂的类型逻辑
function getPropValue<T extends object, Key extends keyof T>(obj: T, key: Key): T[Key] {
return obj[key]
}
/**
* 复杂的类型逻辑
* TypeScript的类型系统是图灵完备的,也就是 能描述各种可计算逻辑. 简单点来理解就是循环 条件等各种JS里面有的语法他都有,JS能写的逻辑他都能写
*/
type ParseParam<Param extends string> = Param extends `${infer Key}=${infer Value}` ?
{
[k in Key]: Value
} : {}
type MergeValues<One, Other> = One extends Other ?
One : Other extends unknown[] ?
[One, ...Other] :
[One, Other]
type MergeParams<
OneParam extends Record<string, any>,
OtherParam extends Record<string, any>
> = {
[Key in keyof OneParam | keyof OtherParam]:
Key extends keyof OneParam
? Key extends keyof OtherParam
? MergeValues<OneParam[Key], OtherParam[Key]>
: OneParam[Key]
: Key extends keyof OtherParam
? OtherParam[Key]
: never
}
type ParseQueryString<Str extends string> = Str extends `${infer Param}&${infer Rest}`
? MergeParams<ParseParam<Param>, ParseQueryString<Rest>>
: ParseParam<Str>
type res = ParseQueryString<'a=1&b=2&c=3'>