这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战
接口是对相对复杂情况的约束
本章主要介绍对象和类中应用到的规范基础
对象接口
对象、函数
先来看(回忆)一下对象和函数的约束:
let num3:object = {a:1}
function fn(arg: object): void {}
上面的函数中参数arg 只是对参数类型进行了规范,arg必须是Object类型。
但是并没有对Object内的键值对做出约束
接口
下面是一个关于接口基础的例子
interface FnArg {
a: number,
c?: number //可选属性;
}
function reLoad(arg: FnArg): void { }
reLoad({ a: 1, c: 2 });
reLoad({ a: 1, c: 3, b: 2 })
解析:
例子中:声明了一个名为FnArg的接口;属性a必选,属性c是可选的。
如果调用reLoad方法时传入的参数中没有属性a,或者传入除a,b之外的其它属性都会报错。
只读属性
给属性添加修饰符readonly
interface Num {
readonly x: number;
}
let numObj: Num = { x: 10 };
numObj.x = 5;
//Cannot assign to 'x' because it is a read-only property.
注:此时属性x是只读,不可更改;修饰符private、public等不可添加;
绕开约束
第一个接口的例子中,对于参数的约束比较严格:属性既不能多,也不能少。
现在重写一下第一个接口的例子:
interface FnArg {
a: number,
c?: number //可选属性;
}
function reLoad(arg: FnArg): void { }
let obj = { a: 1, c: 3, b: 2 }
reLoad(obj)
如果我们提前声明参数obj,等到调用方法的时候再传入obj;
此时如果参数只多不少,是不会报错的。约束就变的比较宽松。
下面的例子中使用断言,达到了同样的效果。
interface FnArg {
a: number,
c?: number //可选属性;
}
function reLoad(arg: FnArg): void { }
reLoad({ a: 1, c: 3, b: 2 } as FnArg);
第三种方式:使用索引类型也可以达到同样的效果。(会在下面提到)
函数接口
函数
先来看一个参数为一个number类型,返回值为number类型的函数
function fn(num1: number): number{
return num1
}
如果有很多同类型的函数,每次都写限制类型会比较麻烦。
接口
通过接口的方式来简化:
interface FnFunc {
(num1: number): number
}
let f2: FnFunc;
f2 = function (num: number) {
return num
}
FnFunc 接口中规范了函数的入参和返回值类型;
推断类型
结合前面章节提到的推断类型,最终如下:
interface FnFunc {
(num1: number): number
}
let f3: fnFunc;
f3 = function (num) {
return num
}
索引类型
索引类型同样是限制的某一个类别,它和字符串、数字这些类型有些区别:
interface Index {
[key: number]: string;
}
// 索引键key,索引值number,索引查询结果类型string;
let arr: Index = [1,3, '3']
/数字1、3不符合;报错;
Index接口中的描述:索引中的键值为数字,返回值为字符串。
它的限制既可以是字符串类型的数组(number索引,查询结果为string)
也可以直接是字符串'lkdjfklsdjfkl'或者其他任何符合描述的类型;
类接口
关键字implements
类接口:应用在类中的接口; 属性和函数的结合
interface Example {
name: string;
run():void;
}
class Father implements Example {
name: number;
run(){}
}
类接口中描述了类中必须的参数、方法;使用一个 接口关键字:implements 不能省略
接口继承接口
接口可以像类一样继承
interface Father {
name: string
}
interface Mom {
sex: string
}
interface Bro extends Father, Mom {
weight: string;
}
如上:接口中的继承可以同时有多个父类;子类中同时拥有多个父类的规范;
接口继承类
接口可以继承类
class Father {
state: string;
}
interface FaInt extends Father {
select(): void;
}
class Son extends Father implements FaInt {
select() { }
}
class Nobody implements FaInt {
state: string;
select() { }
}
解析: 上面的例子中接口FaInt继承自类Father,同时继承了其属性state的约束和state的修饰符public
Son类继承自Father类,所以同时满足state属性和select方法
Nobody类未继承父类,此时Nobody类中必须同时满足state属性和select方法
关于类的基础介绍到此结束;