一、接口
TypeScript 中的接口是一个非常灵活的概念,除了可用于对类的一部分进行抽象以外,也常用于对「对象的形状(Shape)」进行描述。
1、对象接口
用接口来约束参数的类型结构(对象的形状):
- 约定对象的成员数量及类型要求
- 只关注值的外形, 只要传入的对象满足提到的条件,那么它就是被允许的。
- 对象是无序的:类型检查器不会检查属性的顺序,只要相应的属性存在且类型是对的就行。
- 使用接口必须实现里面的必实现项
interface dog{
age: number;
name: string;
}
let d1:dog
d1={
age:1,
name:"小黑",
}
//d1对象必须实现age和name属性
2、可选属性
- 接口里的属性不全都是必需的。 有些是只在某些条件下存在,或者根本不存在。
- 可选属性在应用“option bags”模式时很常用,即给函数传入的参数对象中只有部分属性赋值。
- 带有可选属性的接口与普通的接口定义差不多,在可选属性名字定义的后面加一个
?
符号。
使用好处:
- 可以对可能存在的属性进行预定义;
- 可以捕获引用了不存在的属性(往往是无意之中敲错的代码)时的错误;
注意:可选属性可以不实现,但是一旦实现就必须是声明时的类型
interface dog{
age: number;
name: string;
color?:string //可选实现 但是实现就必须是string类型的
}
let d1:dog
d1={
age:1,
name:"小黑",
color:"black" , //可写可不写,写了就必须是string类型 否则编译报错
}
3、只读属性
一些对象属性只能在对象刚创建的时候修改其值。 可以在属性名前用 readonly
来指定只读属性。
readonly
vs const
:做为变量使用的话用 const
,若做为属性则使用readonly。
注:TypeScript具有
ReadonlyArray<T>
类型,它与Array<T>
相似,只是把所有可变方法去掉了,因此可以确保数组创建后再也不能被修改。
interface dog{
age: number;
name: string;
readonly position:string; //只读属性 不可以修改
}
let d1:dog
d1={
age:1,
name:"wang",
position:"fixed"
}
d1.age=2 //可以修改
d1.position="absulute" //不可以修改:无法分配到 "position" ,因为它是只读属性
二、函数
接口可以描述函数类型;为了使用接口表示函数类型,我们需要给接口定义一个调用签名。它就像是一个只有参数列表和返回值类型的函数定义。参数列表里面的每个参数都需要名称和类型。
1、为函数定义类型
声明式:作用域中直接声明一个函数
function fn(n1: number, n2: any[], n3: Array<string>): number {
return 100 //隐式也能推论出返回值是number 但尽量自己加上函数的返回值类型
}
let result: number = fn(100, [20, true], ["haha"])
console.log(result)
定义式:当做数据引用
let a = function ():void { };
let obj = { fn: function () :void{ } };
let arr = [function ():void { }];
(function (n:number):number { return n*2})(100)
我们可以给每个参数添加类型之后再为函数本身添加返回值类型。 TypeScript能够根据返回语句 自动推断出返回值类型,因此我们通常省略它,但尽量不要省略。
小练习:
定义一个返回值为元组的函数:
function fm(n1:number,n2:string):[number,string]{
return [n1*2,n2]
}
期望再多返回一个数字 : 元组中加一个类型
function fm1(n1:number,n2:string):[number,string,number]{
return [n1*2,n2,100]
}
期望再多返回一个数字 : 元组改为数组
function fm2(n1:number,n2:string):any[]{
return [n1*2,n2,100]
}
2、可选参数和默认参数
传递给一个函数的参数个数必须与函数期望的参数个数一致。
function buildName(firstName: string, lastName: string) {
return firstName + " " + lastName;
}
let result1 = buildName("haha"); // 错误,参数不够
let result2 = buildName("haha", "xixi", "yoyo"); // 错误,超出参数个数
let result3 = buildName("haha", "xixi"); // 正确,与参数个数一致
在TypeScript里我们可以在参数名旁使用 ?
实现可选参数的功能。
注:可选参数必须跟在必选参数后面
function fun(n1:number,n2?:string|undefined):Array<number|string>{
return [n1*2,n2,100] //严格模式下不能将undefined赋值给其他类型,非严格模式可以
}
fun(100) //n2是可选参数,可以传参,也可以不传参,不会报错
fun(100,"haha")
还可以给参数设置默认值,在所有必选参数后面带默认值的参数都是可选的,与可选参数一样,在调用函数的时候可以省略。
function fun1(n2?:string,n1:number=100){
//n1就是可选默认 虽然没有写? 但是只有可选参数才有默认值
}
fun1() //n1,n2都是可选参数,所以此处不传参
注:带默认值的参数不需要放在必选参数的后面。 如果带默认值的参数出现在必须参数前面,用户必须明确的传入
undefined
值从而来获得默认值。
3、剩余参数
在js里面叫rest参数 ...restArr
function rest(n1:number,n2:string,...arg){
console.log(arg) //1,true
}
rest(10,"haha",1,true)
//对rest进行类型约束
function rest1(n1:number,n2:string,...arg:[number,string]){
console.log(arg) //[1,"haha"]
}
rest1(10,"haha",1,"haha") //剩余参数类型是元组 只能传两个且为numer和string
function fg(n1:number,n2:string,...rest:[number,string]):[any[],Array<number>]{
return [[10,20,true],[10,20]]
}
fg(100,"haha",10,"xixi")
4、函数类型变量
声明函数类型时用" => "," => "后必须写函数返回值类型 无返回值为空时也必须写void
- 变量的类型可以声明为函数类型:
let myAdd: (x: number, y: number) => number = function(x: number, y: number): number { return x + y; };
//这里的 => 不是箭头函数,而是表示在声明函数的类型
- 函数类型属于自定义类型,包含两部分:参数类型和返回值类型:
//声明一个变量并指定类型为自定义的函数类型
let myadd:(x:number, y:number)=>number;
//声明一个函数
function add(x: number, y: number): number {
return x + y;
}
//把函数赋值给类型为函数类型的变量
myadd = add;
//赋值匿名函数
myadd = function(x: number, y: number): number {
return x + y;
}
//赋值箭头函数
myadd = (x: number, y: number):number=>{
return x + y;
}
- 只要参数类型是匹配的,那么就认为它是有效的函数类型,并不要求参数名一样,很多时候参数名是为了增加可读性
let myAdd: (baseValue: number, increment: number) => number =
function(x: number, y: number): number { return x + y; };
- 在函数和返回值类型之前使用(
=>
)符号,返回值类型是函数类型的必要部分,如果函数没有返回任何值,你也必须指定返回值类型为void
而不能留空。
5、使用接口封装函数变量类型
自定函数类型代码往往很长,可以使用接口来封装该类型,之后使用接口来代表该类型
interface myfun1{
//函数格式:
():number
}
let my1:myfun1 //myfun1接口代表my1类型的函数
my1=():number=>{return 100}
interface myfun2{
//函数格式:
(number,string):number
}
let my2:myfun2 //myfun2接口代表my2类型的函数
my2=function(arg1:number,arg2:string):number{return 111}