在TypeScript中定义对象的方式要用关键字interface。但是在众多的中文资料里关于interface的理解都是一种对于数据的约束,让数据的结构满足约束(interface)
的格式。
//这样写是会报错的 因为我们在person定义了a,b但是对象里面缺少b属性
//使用接口约束的时候不能多一个属性也不能少一个属性
//必须与接口保持一致
interface Person {
a:string,
b:string
}
// WRONG
const person:Person = {
a:"213"
}
// OK
const person:Person = {
a:"我"
b:"你"
}
在这里特别强调了不能多一个属性也不能少一个属性,可能是因为在JavaScript中给1个Object增加属性是一个非常自然的事情。比如下面这样:
let obj = {
name: "Adam"
}
let obj.age = 20
可选属性
顾名思义就是就是该属性可以不存在。
在想要标记为可选属性
的属性名后+1个?
就了。
那么在进行一些数据结构构造的时候,即使该属性没有定义也符合interface的约束。
//可选属性的含义是该属性可以不存在
//所以说这样写也是没问题的
interface Person {
a:string,
b?:string //可选属性
}
// OK
const person:Person = {
a:"213"
}
任意属性需要通过索引签名(indexSignatures)
来实现。
当你声明一个索引签名时,所有明确的成员都必须符合索引签名。
//在这个例子当中我们看到接口中并没有定义C但是并没有报错
//应为我们定义了[propName: string]: any;
//允许添加新的任意属性
interface Person {
a:string,
b?:string,
[propName: string]: any; //索引签名
}
const person:Person = {
a:"213",
c:"123"
}
[propName: string]: any
经常使用在前端接受后端返回数据时的场合。当我们只能确定肯定需要a属性而不确定是否需要其他属性时可以在这样。
经过了解后才发现索引签名是一个非常复杂的东西,具体的可以看下面这篇blog
索引签名 | 深入理解 TypeScript
举一个小小的例子,剩下的就看blog吧
// OK
let a: { [propName: string]: any } = {
c: '123',
d: '123',
e: '123'
}
被readonly修饰的属性只能读不能修改
interface Person {
readonly a: string, //只读
b?: string,
}
let person: Person = {
a: '123',
}
//Cannot assign to 'a' because it is a read-only property.
person.a='a'
// OK
person.b='b'
在interface中也可以声明一个属性类型为function。
interface Person {
f: (num1: number, num2: number) => number
}
let person: Person = {
f: (n1, n2): number => { return num1 + num2; }
}
let num1 = 1;
let num2 = 2;
console.log(person.f(num1, num2)); // output