TypeScript笔记(三)

1.unknown

unknown

unknown类型,任何类型都可以赋值为unknown类型。 它是 any 类型对应的安全类型

1
2
3
let unknown:unknown;
unknown = 'zf';
unknown = 11;

不能访问unknown类型上的属性,不能作为函数、类来使用

  • 联合类型中的unknown

    1
    type UnionUnknown = unknown | null | string | number

    联合类型与unknown都是unknown类型

  • 交叉类型中的unknown

    1
    type inter = unknown & null

    交叉类型与unknown都是其他类型

unknown特性

  • never是unknown的子类型

    1
    type isNever = never extends unknown ? true : false;=
  • keyof unknown 是never

    1
    type key = keyof unknown;
  • unknown类型不能被遍历

    1
    unknown类型不能被遍历

    unknown类型不能和number类型进行 +运算,可以用于等或不等操作

unknown 和 any 都是顶级的类型

1
2
3
4
5
type keys1 = keyof any;
type keys2 = keyof unknown; //unknown 是无法识别的类型 没有key

type unionUnknown = unknown | string | true | false; // unknown 任何类型都可以赋予给unknown
type interUnknown = unknown & string; // string

如果无法确定的类型 不要贸然采用any

any不校验 意味着可以调用 可以取值

1
2
let a: unknown = 1; // unknown 是any的安全类型

如果标识为unknown 类型 必须先类型保护再去使用 (收窄类型 在使用)

1
2
3
4
5
6
7
8
9
10
11
12
13
function isNumber(val: unknown): val is number {
return typeof val === "number";
}
function isString(val: unknown): val is string {
return typeof val === "string";
}

if (isNumber(a)) {
a.toFixed; //
} else if (isString(a)) {
a.charCodeAt;
}

2.自定义类型

Diff实现

求两个对象不同的部分

1
2
3
4
5
6
7
8
9
10
let person1 = {
name: 'zhufeng',
age: 11,
address: '回龙观'
}
let person2 = {
address: '回龙观',
}
type Diff<T extends object,K extends Object> = Omit<T,keyof K>
type DiffPerson = Diff<typeof person1,typeof person2>

InterSection交集

1
2
3
4
5
6
7
8
9
10
let person1 = {
name: 'zhufeng',
age: 11,
address: '回龙观'
}
let person2 = {
address: '回龙观',
}
type InterSection<T extends object, K extends object> = Pick<T, Extract<keyof T, keyof K>>
type InterSectionPerson = InterSection<typeof person1, typeof person2>

Overwrite属性覆盖

1
2
3
4
5
6
7
type OldProps = { name: string, age: number, visible: boolean };
type NewProps = { age: string, other: string };

type Diff<T extends object,K extends Object> = Omit<T,keyof K>
type InterSection<T extends object, K extends object> = Pick<T, Extract<keyof T, keyof K>>
type Overwrite<T extends object, K extends object, I = Diff<T,K> & InterSection<K,T>> = Pick<I,keyof I>
type ReplaceProps = Overwrite<OldProps, NewProps>

如果存在已有属性则使用新属性类型进行覆盖操作

Merge对象合并

1
2
3
type Compute<A extends any> = { [K in keyof A]: A[K] };
type Merge<T, K> = Compute<Omit<T, keyof K> & K>;
type MergeObj = Merge<OldProps,NewProps>

将两个对象类型进行合并操作

自己实现一些常用的类型

内置类型 基于条件类型的 Extract Exclude 集合类型

基于映射的类型 Partial Required Readonly 修饰

结构的 Pick Omit Record 结构处理

基于推断的类型 InstanceType ReturnType Paramters…. infer (模式匹配类型)

1
2
3
4
5
6
7
8
9
10
type T1 = {
name: "ac";
age: number;
address: string;
};
type T2 = {
name: string;
gender: number;
address: number;
};
  1. (先找到name,和 address 排除掉) 和 (name,address 添加可选)
1
2
3
4
5
6
7
// 1. (先找到name,和 address 排除掉)  和 (name,address 添加可选)
type Compute<T extends object> = {
[K in keyof T]: T[K];
};
type PartialPropsOptional<T extends object, K extends keyof T> = Omit<T, K> &
Partial<Pick<T, K>>;
type PPO = Compute<PartialPropsOptional<T1, "name" | "address">>;

2.我期望 去t1 中 取出 值是string类型

1
2
3
4
5
6
7
8
9
10
11
12
type isEqual<T, K, S, F> = T & {} extends K ? (K & {} extends T ? S : F) : F;

// {name:never, age:never, address:'address'}
type ExtractKeyByValue<T extends object, U> = {
[K in keyof T]: isEqual<T[K], U, K, never>;
}[keyof T]; // string |

// 可索引接口
type PickKeysByValue<T extends object, K> = Pick<T, ExtractKeyByValue<T, K>>;
// 用户在使用类型的时候 希望的是简单, 内部复杂写
type ReturnPickKeysByValue = PickKeysByValue<T1, string>;

3.我期望去掉string 类型

1
type isEqual<T, K, S, F> = T & {} extends K ? (K & {} extends T ? S : F) : F;
1
2
3
4
5
6
7
8
9
10
11
// {name:never, age:never, address:'address'}

type ExtractKeyByValue<T extends object, U> = {
[K in keyof T]: isEqual<T[K], U, K, never>;
}[keyof T]; // string |


// {never:xxx,address:string,never:xxx}
type ExtractKeyByValue<T extends object, U> = {
[K in keyof T as isEqual<T[K], U, K, never>]: T[K]; // 冲映射
}; // string |

可索引接口

1
2
3
4
5
6
type PickKeysByValue<T extends object, K, O = true> = isEqual<
O,
true,
Omit<T, ExtractKeyByValue<T, K>>,
Pick<T, ExtractKeyByValue<T, K>>
>;

用户在使用类型的时候 希望的是简单, 内部复杂写

1
type ReturnPickKeysByValue = ExtractKeyByValue<T1, string>;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
type T1 = {
name: "ac";
age: number;
address: string;
};
type T2 = {
name: string;
gender: number;
address: number;
};
// 对象求交集
type ObjectInter<T extends object, K extends object> = Pick<
T,
keyof T & keyof K
>;
type X1 = ObjectInter<T1, T2>;

// 对象求差
// Omit + Extract == Pick exclude
type ObjectDiff<T extends object, K extends object> = Omit<T, keyof K>;
type X2 = ObjectDiff<T1, T2>;

// 两个类型合并在一起,如果都有的属性 用T2的 ? {...T1,...T2}

// T1 - T2 + T2 - T1 + T2 & T1

type OverWrite<T extends object, K extends object> = ObjectDiff<T, K> &
ObjectDiff<K, T> &
ObjectInter<K, T>;
type X3 = Compute<OverWrite<T1, T2>>;

// merge 类型会合并在一起
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<K, T> &
MergeType<T, K>;
type X4 = Compute<MergeWrite<T1, T2>>;

// ------

// type O1 = { top: number; bottom?: never };
// type O2 = { bottom: number; top?: never };

// let o: O1 | O2 = {
// bottom: 100,
// };

interface Man1 {
fortune: string;
}
interface Man2 {
funny: string;
}
interface Man3 {
foreign: string;
}

type DiffType<T, U> = {
[K in Exclude<keyof T, keyof U>]?: never;
};

// man1- man2 + man2
// man2 -man1 + man1
type OrType<T, K> = (DiffType<T, K> & K) | (DiffType<K, T> & T);

let man: OrType<Man3, OrType<Man1, Man2>> = {
funny: "ed",
};