复习一下
可选
type Partial<T> = {
[P in keyof T]?: T[P];
};
必选
type Required<T> = {
[P in keyof T]-?: T[P];
};
只读
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
排除
type Exclude<T, U> = T extends U ? never : T;
提取
type Extract<T, U> = T extends U ? T : never;
选择 选出自己想要的
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
//省略 不想要的属性
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
对象优化
type Record<K extends keyof any, T> = {
[P in K]: T;
};
//不为空
type NonNullable<T> = T & {};
//推导函数返回类型
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
interface Bird{
kind:'鸟',
fly:string;
}
interface Fish{
kind:'鱼',
swim:string;
}
//联合类型以后可以基于差异化来判断,先具体到某一类型后再使用
通过各种判断来缩小范围
function getAimal(val:Bird|Fish){
if('fly' in val){
val
}else{
val
}
或者
if(val.kind=='鸟'){
val.fly
}else{
val.swim
]
}
再举个例子
function ensureArray<T>(input:T|T[]){
return Array.isArray(input)?input:[input]
}
let r1=ensureArray('abc')
let r2=ensureArray(['abc'])
函数嵌套不识别问题解决 基于上下文的推导会因为作用域发生变化产生问题 ts无法识别的使用使用断言
function addType(val?:number){
val=val||0;
return function(type:string){
return type+(val as number).toFixed();
}
}
addType(100)('S')
或者用ts 的返回值类型来判断
interface Bird{
kind:'鸟',
fly:string;
}
interface Fish{
kind:'鱼',
swim:string;
}
function isBird(val:Bird|Fish):val is Bird{
return 'fly' in val
}
function getAimal(val:Bird|Fish){
if(isBird(val)){
}else{}
}
把T1的name跟address变成可选
type T1={
name:number,
age:number,
address:string
}
type Compute<T extens keyof any>={
[K in keyof T]:T[K]
}
type PartialPropsOption<T extends object,K extends keyof T>=Omit<T,K>&Partial<Pick<T,K>>
type Result= Compute<PartialPropsOption<T1,'age'|'K'>>
嗦一下思路,先用omit 省略不想要的,再用pick提取想要的 然后Partial可选一下想要的Compute重新映射一下类型
全等判断
type isEqual<T,K,S,F>=T&{}extends K?(K&{}extends T?S:F):F
从T1中去取出值是string的类型
type T1={
name:number,
age:number,
address:string
}
type PickKeysByValue<T extends object,U>={
[K in keyof T]:T[K] extends U? T[]:never
}
type Result=PickKeysByValue<T1,string>
通过全等判断演变一下
type PickKeysByValue<T extends object,U>={
[K in keyof T]:isEqual<T[K],U,K,never>
}
type Result=PickKeysByValue<T1,string>;
这时候返回类型还是包含never的字段属性的
而联合属性里type a=string|never
合并后类型只有string属性
再改进一下
type PickKeysByValue<T extends object,U>={
[K in keyof T]:isEqual<T[K],U,K,never>
}[K keyof T]//这里keyof 方括号返回的是索引
备注一下正常返回的是
type Result = {
name: never;
age: never;
address: string;
}
这么一个类型
而方括号[]是索引的意思
Result['name'|'age'|'address']
我™骚索引搞了个联合类型硬生生返回了个string
焯!!!!
前面是通过属性拿到address的键值对类型,下面通过建名拿到键值对
type PickValue<T extends object,K extends keyof T>=Pick<T,K>
type Result2=PickValue=<PickValue<T1,PickKeysByValue<T1,string>>
方法在进化一下
type ExtractKeyBayValue<T extends object,U>={
[K in keyof T]:isEqual<T[K],U,K,never>
}[keyof T]
type PickKeysByValue<T extends object,K>=Pick<T,ExtractKeyValue<T,K>>;
type ReturnPickKeysByValue=PickKeysByValue<T1,string>
再进化一下
type PickKeysByValue<T extends object,K,O=true>=isEqual<
O,
true,
Omit<T,ExtractKeyByValue<T,K>>,
Pick<T,ExtractKeyByValue<T,K>>
>
type ReturnPickKeysByValue=PickKeysByValue<T1,string,true>
之前的ExtrackKeyByValue还可以优化
通过键值内部重命名并判断值如果值正常就返回对应的键值对
type ExtractKeyBayValue<T extends object,U>={
[K in keyof T as isEqual<T[K],U,K,never>]:T[K]
}
type T1={
name:number,
age:number,
address:string
}
type T2={
name:number,
age:number,
address:string
}
// 求交集
type ObjectInter<T extends object,K extends object>=Pick<T,keyof T&keyof K>
// 求差
type ObjectDiff<T extends object,K extends object>=Omit<T,keyof K>
//求{。。。T1,...T2}
type OverWrite<T extends object,K extends object>=ObjectDiff<T,K>&
ObjectDiff<K,T>&ObjectInter<K,T>
// 合并
type MergeType<T,U>={
[K in keyof T]:K extends keyof U?T[K]|U[K]:T[K]
}
//求差鸡 跟其他属性交集的部分联合在一起就行
type MergeWrite<T extends object,K extends object>=ObjectDiff<T,K>&
ObjectDiff<K,T>&ObjectInter<K,T>
//属性互斥
interface M1{
fortune:string
}
interface M2{
funny:string
}
interface M3{
foreign:string
}
type DiffType<T,U>={
[K in Exclude<keyof T,keyof U>]?:never;
}
type OrType<T,K>=(DiffType<T,K>&K)|(DiffType<K,T>&T);
let man:OrType<M3,OrType<M1,M2>>={
fortune:'1',
funny:'2' //这时会出现互斥提示 ,这是三个属性互斥
}