implements子句
类可以实现接口,使用关键字implements
可以使用一个implements子句来检查一个类,是否满足了一个特定的接口。如果一个类不能正确地实现它,就会发出一个错误
注意点:
实现一个带有可选属性的接口并不能创建该属性
只要一个接口继承了某个类,那么就会继承这个类中所有的属性和方法,但是只会继承属性和方法的声明,不会继承属性和方法实现
与extends的区别
extends:继承某个类,继承之后可以使用父类的方法,也可以重写父类的方法
implements:继承某个类,必须重写才可以使用
export default {}
interface IpersonInfo{
name:string
age:number
sex?:string
show():void
}
interface IMusic{
music:string
}
class Person implements IpersonInfo,IMusic{
name:string="杨幂"
age:number=18
// sex:string="女"
music:string="爱的供养"
show(){
console.log(`我是${this.name},年龄是${this.age},主演古剑奇谭`)
}
}
let p = new Person
p.show()
interface ITest extends Person{
salary:number
}
class Star extends Person implements ITest{
salary: number=10000000
name:string="赵丽颖"
}
let s = new Star()
console.log(s.salary)
console.log(s.name)
泛型
泛型的基本使用
泛型可以理解为宽泛的类型,通常用于类和函数。使用的时候我们再指定类型
泛型不仅可以让我们的代码变得更加健壮,还能让我们的代码在变得健壮的同时保持灵活性和可重用
·通过用<T>来表示,放在参数的前面
export default {}
// const arr1:string[]=["请问","阿斯顿","自行车"]
// const arr2:Array<string>=["请问","阿斯顿","自行车"]
// const arr3:Array<number>=[1,2,3,4,5]
// let res = new Array(3).fill("自行车")
// console.log(res)
// let getArray = (value:number,items:number):number[]=>{
// return new Array(items).fill(value)
// }
// let res1 = getArray(10,5)
// console.log(res1)
// let getArray = (value:any,items:number):any[]=>{
// return new Array(items).fill(value)
// }
// let res2 = getArray("刘亦菲",5)
// let res3 = getArray(10,5)
// console.log(res2)
// console.log(res3)
let getArray = <T>(value:T,items:number):T[]=>{
return new Array(items).fill(value)
}
let res4 = getArray<string>("刘亦菲",5)
console.log(res4)
let res5 = getArray<number>(6,5)
console.log(res5)
泛型约束
在TS中,我们需要严格的设置各种类型,我们使用泛型之后,将会变得更加灵活,但同时也将会存在一些问题
我们需要对泛型进行约束来解决这些问题
export default {}
// function getLength<T>(arr:T):T{
// console.log(arr.length)
// return arr
// }
// function getLength<T>(arr:Array<T>):Array<T>{
// console.log(arr.length)
// return arr
// }
// getLength([1,2,3,4,5])
// getLength(["刘亦菲","杨幂","赵丽颖"])
// getLength("刘亦菲")
interface ILength{
length:number
}
function getLength<T extends ILength>(arr:T):number{
return arr.length
}
getLength([1,2,3,4,5])
getLength(["刘亦菲","杨幂","赵丽颖"])
getLength("刘亦菲")
泛型接口
将泛型与接口结合起来使用,可以大大简化我们的代码,增加我们的代码可读性
泛型也可以使用默认值
export default {}
// interface IPerson<T1,T2>{
// name:T1
// age:T2
// }
// let p:IPerson<string,number>={
// name:"刘亦菲",
// age:18
// }
// console.log(p)
interface IPerson<T1=string,T2=number>{
name:T1
age:T2
}
let p:IPerson={
name:"刘亦菲",
age:18
}
console.log(p)
泛型类
泛型类看上去与泛型接口差不多。泛型类使用()括起泛型类型,跟在类名后面。
export default {}
// <>里T有几个取决于有几种属性类型
class Person<T1,T2>{
name:T1
age:T2
sex:T1
constructor(name:T1,age:T2,sex:T1){
this.name=name
this.age=age
this.sex=sex
}
}
let p = new Person<string,number>("刘亦菲",18,"女")
console.log(p)
其他补充类型
unknown类型
ounknown类型代表任何值。这与any类型类似,但更安全,因为对未知unknown值做任何事情都是不合法的。
unknown类型被称作安全的any
1.任何类型都可以赋值给unknown类型
2.不能将unknown类型赋值给其它类型
3.unknow与其它任何类型组成的交叉类型最后都是其它类型
4.unknown除了与any以外,与其它任何类型组成的联合类型最后都是unknown类型
5.never类型是unknown类型的子类型
export default {}
// 1.任何类型都可以赋值给unknown
let str:unknown;
str="刘亦菲"
str=18
str=true
// 2.不能将unknown类型赋值给其他类型
let val:unknown=18
let num:number
// num=val
// 类型断言
num=val as number
// 类型缩小
if(typeof val=="number"){
num=val
}
// 3.unknown类型与其他类型组成的交错类型最后都是其他类型
type MyType = number & unknown
type MyType2 = unknown & string
// 4.unknown除了与any,与其他类型组成的联合类型最后都是unknown类型
type MyType3 = unknown | string
type MyType4 = number | unknown
type MyType5 = unknown | any
// 5.never类型是unknown类型的子类型
type MyType6 = never extends unknown?true:false
map类型
Map对象保存键值对,并且能够记住键的原始插入顺序。
任何值(对象或者原始值)都可以作为一个键或一个值。
Map是 ES6中引入的一种新的数据结构
可以使用for of进行迭代
创建map:
let myMap = new Map()
Map相关的函数与属性:
map.clear()-移除Map对象的所有键/值对。
map.set()-设置键值对,返回该Map 对象。
map.get()-返回键对应的值,如果不存在,则返回undefined,。
map.has()-返回一个布尔值,用于判断Map中是否包含键对应的值。
map.delete() –删除Map中的元素,删除成功返回true,失败返回false。
map.size -返回Map对象键/值对的数量。
map.keys()-返回一个lterator对象,包含了Map对象中每个元素的键。
map.values()-返回一个新的lterator对象,包含了Map对象中每个元素的值。
export default {}
let nameMap = new Map()
// 设置Map对象
nameMap.set("刘亦菲",1)
nameMap.set("杨幂",2)
nameMap.set("赵丽颖",3)
// 获取键对应的值
// console.log(nameMap.get("刘亦菲"))
// console.log(nameMap.get("刘亦菲1"))
// 判断Map中是否包含键对应的值
// console.log(nameMap.has("杨幂"))
// console.log(nameMap.has("唐嫣"))
// 返回Map对象键/值对的数量
// console.log(nameMap.size)
// 删除
// console.log(nameMap.delete("赵丽颖"))
// console.log(nameMap.delete("赵丽颖1"))
// 移除Map对象的所有键/值对
// nameMap.clear()
// console.log(nameMap)
// 迭代Map中的key
// for(let key of nameMap.keys()){
// console.log(key)
// }
// 迭代Map中的value
// for(let value of nameMap.values()){
// console.log(value)
// }
// 使用对象解析
for(let [key,value] of nameMap){
console.log(key,value)
}
条件类型
条件类型的形式看起来有点像JavaScript中的条件表达式.
T extends U ? TrueType : FalseType
·应用场景:解决函数重载问题
export default {}
// 三元运算符
// let f = 60
// let j =""
// j=f>=60?"及格":"不及格"
// console.log(j)
interface IName{
name:string
}
interface IAge{
age:number
}
// 条件类型
type Condition<T>=T extends string?IName:IAge
function reload<T extends string|number>(idOrname:T):Condition<T>{
throw ""
}
reload("赵丽颖")
reload(18)
映射类型
当你不想重复定义类型,一个类型可以以另一个类型为基础创建新类型。通俗的说就是,以一个类型为基础,根据它推断出新的类型
Readonly / Partial关键字
Record / Pick映射类型
Readonly,Partial和 Pick是同态的,但Record不是。因为Record并不需要输入类型来拷贝属性,所以它不属于同态
export default {}
// Record映射类型
// 他会将一个类型的所有属性值都映射到另一个类型上并创造一个新的类型
type Name="person"|"animal"
type Person={
name:string
age:number
}
type NewType=Record<Name,Person>
let res:NewType={
person:{
name:"富兰克林",
age:18
},
animal:{
name:"小查",
age:3
}
}
console.log(res)
// Pick映射类型
// 将原有类型中的部分内容映射到新类型中
interface IPerson{
name:string
age:number
}
type MyType=Pick<IPerson,"name">
let res2:MyType={
name:"崔弗"
}
console.log(res2)