TS笔记
1.type和interface的区别和相同点
type: 类型别名
作用:可以给类型另取名字,可组合
1.type MyType = number;//可以让MyType具有number类型的作用
2.type MyType = number | string; //可以让MyType具有联合类型效果
3.type MyType = {
str:string,
num:number,
fun:function
[propsName:string]
};//也可以具有判断对象类型的作用
interface:接口
作用:与type作用相同,但只可以定义对象属性类型
interface MyType {
//内部与type定义对象属性类型一样
}
相同点
1.两者都可以给对象或者函数进行类型定义
2.都支持扩展
type MyTpe ={
str:string
}
type OtherType = MyTpe & {
num:number
}
interface MyType = {
str:string
}
interface OtherType extends MyType = {
num:number
}
不同点
1.type可以为基本类型、联合类型或元组类型,interface不可以
2.同名interface 自动合并 ,type则不可以,type重复定义会报错
使用场景
type: 定义基本类型、联合类型、函数类型、映射类型、元组类型时
interface: 需要接口自动合并、定义对象类型且无需使用type
2.泛型变量的理解
function test<T,U>(value:T,message:U):T {
return value
}
console.log(test<number,string>(1111,'str'))
上述例子中第一个T 是传递给test函数参数的类型占位符, T表示Type 类型 可以用任何有效字符代替,常见的泛型变量还有:K (表示对象中键的类型)、V(表示对象值得类型)、E(表示元素类型)
这些泛型是为了在你使用函数时给函数的传参或者返回值动态定义类型
3.交叉类型的理解
含义:类型和类型 用 ’&‘交叉运算符结合变成交叉类型
特性:唯一性------- A&A <=> A
满足交换律------- A&B <=>B&A
满足结合律------- (A&B)&C <=> A&(B&C)
父类型收敛------- 如果B是A的父类型, 则A & B 将被收敛成A类型
//父类型收敛例子
type A0 = 1 & number;//1
type A1 = "1" & string;//"1"
type A2 = any & 1; // any 除了never类型外 与任何类型交叉都是any
type A3 = any & never // never
interface A {
x:number;
y:number;
}
interface B {
name:string;
}
A & B // {x:number;y:number;name:string}
//具有相同属性名称但类型不一,且是基本数据类型
interface A {
x:number;
y:number;
}
interface B {
x:string;
}
A & B // {x:number;y:number;name:string}
const index: A&B = {x:1,y:1} //x报不能将number分配给never
//为什么是never呢 因为 A & B 的x 相当于 string & number 既是字符串又是数字的类型不存在
//在复杂的对象属性类型中 具有相同属性时
interface A {a:numebr};
interface B {b:string};
interface C {c:boolean};
interface D {x:A};
interface E {x:B};
interface D {x:C};
type ABC = A & B & C;
const data:ABC = {
x:{
a:1,
b:'str',
c:true
}
}//还会按需进行合并
//如果交叉运算中包含联合类型,则最终运算结果为never
type A = {
num:number,
str:string
}
type B = {
num:string
str:string
}
type C = {
num:boolean // true | false
str:string
}
type AB = A&B;//{num:never;str:string}
type AC = A & C //never类型
函数交叉运算
type F1 = (a:string,b:string) => void;
type F2 = (a:number,b:number) => void;
type F3 = (a:number,b:string) => void;
const f:F1 & F2 = (a:string|number,b:string | number)=>{}
f('str','str')//不会报错
f(1,2)//不会报错
f(1,'str')//会报错 解决方法 则 类型中再加上F3即可
4.映射类型理解
含义:根据所需将定义好的类型进行映射,可以将指定属性变为只读、必填、可选
总而言之,是一种泛型,可以将原来的类型映射成新的类型
作用:减少重复代码的使用
语法:{[P in K] :T} {[P in K] ?:T} {[P in K] -?:T} { readonly[P in K] :T}
{ readonly[P in K] ?:T} { -readonly [P in K]? :T }
用法:{ readonly [P in K]? :T } ; 添加readonly表示只读修饰符,添加?表示可选 ,且不加任何修饰符,默认为只读
例子:
type Element = {a:string;b:number;c:boolean}
type Example1 = {[P in "x" | "y"]:number} // {x:number,y:number}
type Example2 = {[P in "x" | "y"]:P} // {x:"x",y:"y"}
type Example3 = {[P in "a" | "b"]:Element[P]} // {a:string,b:number}
type Example3 = {[P keyof Element]:Element[P]} // {a:string;b:number;c:boolean}
type User = {
name:string,
password:number,
phone:number
}
type MyInfo = {
[P in keyof User]?: User[P]
}
type UserInfo = MyInfo<User> => {
name?:string,
password?:number,
phone?:number
}
interface Test {
kind:'goKind',
radius:number
}
type DeleteAttrKind<T> = {
[K in keyof T as Exclude<K,'kind'>]:T[K]
}
type Exclude<T,U> = T extends U ? never:T//键重新映射时as子句返回never类型,该键会被删除
type GoKind=DeleteAttrKind<Test> => { radius:number}