
【TS学习系列】5.接口
Typescript中接口不仅能够作用于类中,还能为属性、函数、可索引的类型提供约束和规范。它的核心原则之一就是为值所具有的结构进行类型检查。
接口初探
下面通过一个简单示例来观察接口是如何工作的:
function sayHello(person: {name: string}): void {
console.log("Hello,My name is " + person.name);
}
let pJane = {sex: "girl",name: "Jane",age: 13};
sayHello(pJane);
类型检查器会检查sayHello的调用,这里会要求该方法的参数满足Person
类型的约束。 需要注意的是,我们传入的对象参数实际上会包含很多属性,但是编译器只会检查那些必需的属性是否存在,并且其类型是否匹配。 然而,有些时候TypeScript却并不会这么宽松:
下面我们重写上面的例子,这次使用接口来描述:必须包含一个name
属性且类型为string
:
interface Person{
name: string;
}
function sayHello(person: Person): void {
console.log("Hello,My name is " + person.name);
}
let pJane = {sex: "girl",name: "Jane",age: 13};
sayHello(pJane);
Person
接口就好比一个人,用来描述上面例子里的要求。 它代表了有一个 name
属性且类型为string
的对象。 需要注意的是,我们在这里并不能像在其它语言里一样,说传给 sayHello
的对象实现了这个接口。我们只会去关注值的外形。 只要传入的对象满足上面提到的必要条件,那么它就是被允许的。
还有一点值得提的是,类型检查器不会去检查属性的顺序,只要相应的属性存在并且类型也是对的就可以。
可选属性
接口里的属性不全都是必需的。 有些是只在某些条件下存在,或者根本不存在。 可选属性在应用“option bags”模式时很常用,即给函数传入的参数对象中只有部分属性赋值了。
下面是应用了“option bags”的例子:
interface CardConfig{
type?: string;
width?: number;
}
function createCard(cardConfig: CardConfig): {type: string,size: number}{
let newCard = {type: "queen",size: 100};
if(cardConfig.type) {
newCard.type = cardConfig.type;
}
if(cardConfig.width) {
newCard.size = cardConfig.width * cardConfig.width;
}
return newCard;
}
let myCard = createCard({type:"king"});
带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个?
符号。
可选属性的好处之一是可以对可能存在的属性进行预定义,好处之二是可以捕获引用了不存在的属性时的错误。 比如,我们故意将 createCard
里的type
属性名拼错,就会得到一个错误提示:
interface CardConfig{
type?: string;
width?: number;
}
function createCard(cardConfig: CardConfig): {type: string,size: number}{
let newCard = {type: "queen",size: 100};
if(cardConfig.type) {
//Property 'typ' does not exist on type 'CardConfig'. Did you mean 'type'?ts(2551)
newCard.type = cardConfig.typ;
}
if(cardConfig.width) {
newCard.size = cardConfig.width * cardConfig.width;
}
return newCard;
}
let myCard = createCard({type:"king"});
可读属性
一些对象属性只能在对象刚刚创建的时候修改其值。 你可以在属性名前用 readonly
来指定只读属性:
interface Point{
readonly x: number;
readonly y: number;
}
你可以通过赋值一个对象字面量来构造一个Point
。 赋值后, x
和y
再也不能被改变了。
let p1: Point = { x: 10, y: 20 };
//Error Cannot assign to 'x' because it is a read-only property.ts(2540)
p1.x = 5;
TypeScript具有ReadonlyArray
类型,它与Array
相似,只是把所有可变方法去掉了,因此可以确保数组创建后再也不能被修改:
let nums: number[] = [1, 2, 3, 4, 5];
let iNums: ReadonlyArray = nums;
//Index signature in type 'readonly number[]' only permits reading.ts(2542)
iNums[0] = 10;
//Property 'push' does not exist on type 'readonly number[]'.ts(2339)
iNums.push(12);
//Cannot assign to 'length' because it is a read-only property.ts(2540)
iNums.length = 14;
//The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.ts(4104)
nums = iNums;
上面代码的最后一行,可以看到就算把整个ReadonlyArray
赋值到一个普通数组也是不可以的。 但是你可以用类型断言重写:
nums = iNums as number[];
readonly
vs const
最简单判断该用readonly
还是const
的方法是看要把它做为变量使用还是做为一个属性。 做为变量使用的话用 const
,若做为属性则使用readonly
。


您可能也喜欢

JavaScript小知识:with改变作用域
2020年4月22日
Android 解决系统字体变大导致WebView页面显示错乱问题
2020年4月17日