// js:const getPersonName = person => {console.log(person.name);}const setPersonName = (person, name) => {person.name = name;}
我们这种js的语法其实是有一些问题的,如果传进来的person是一个undefined,那么语句执行的时候就会报错了。
我们为了避免错误:让person中一定要有name属性,可以使用类型注解:
const getPersonName = (person: {name: string}) => {console.log(person.name);}const setPersonName = (person: {name: string}, name: string) => {person.name = name;}
这里我们发现有一些重复的数据定义,这个时候可以使用interface定义通用类型,定义一次即可:
interface Person {name: string}const getPersonName = (person: Person) => {console.log(person.name);}const setPersonName = (person: Person, name: string) => {person.name = name;}
所以如果有通用的类型,我们就可以用interface表示出来。
type 和 interface,区别不大但是还是有区别的:
type可以直接代表一个基础类型,但是interface只能代码对象或者函数
type Person = string; // type 是可以这样使用代表 string 的 但是interface 不能代表基础类型
在ts中我们一般能用接口 interface就用interface, 不行再考虑使用类型别名 type
如果我们把interface 做一些修改:
interface Person {name: string,age: number}....// 这里如果这样写代码就会报错了,因为接口要求我们传入age,但是我们没有传递。所以只能写入一个ageconst p1 = {name: 'cos'}getPersonName(p1);setPersonName(p1, 'rose');
但是存在一些情况下,我们有些时候,需要age, 有些时候不需要age,这时候,可以这样写:
interface Person {name: string,age?: number // 表示这个age 是可有可无的。}
如果我们希望某个属性是只读的,可以使用readonly
interface Person {readonly name: string,age?: number}

如果这样写,其实是不会报错的,
interface Person {name: string,age?: number}...const p1 = {name: 'cos',gender: 'male'}getPersonName(p1);...
但是如果我们以一种字面量的形式传递参数是会报错的。比如:

注意:当使用字面量的形式直接传递一个对象给变量的时候,TS会对类型进行强校验。
这样其实也是有问题的,比如,我的对象中具体有什么属性是不确定的,某个属性可能有、也可能没有。这样的话就会有问题了。我们可以这么写:
interface Person {// readonly name: string,name: string,age?: number,[propsName: string]: any // 表示,这个属性,属性名是字符串,值可以是任意类型}// 这样多出其他属性也是ok的。const p1 = {name: 'cos',gender: 'male',job: 'web'}
接口中不仅可以存一些属性也可以存储一些方法。
interface Person {// readonly name: string,name: string,age?: number,[propsName: string]: any,say(): string // 定义一个方法 say , 返回值为字符串}// 这时候其实就需要定义一个say 方法,并返回字符串。否则就会报错。const p1 = {name: 'cos',gender: 'male',job: 'web',say() {return 'say hi'}}getPersonName(p1);
一个类应用一个接口,那么这个类里面就必须具备这个接口中的属性, 否则这个类就会报错。
interface Person {// readonly name: string,name: string,age?: number,[propsName: string]: any // 表示,这个属性,属性名是字符串,值可以是任意类型say(): string // 定义一个方法 say , 返回值为字符串}...// 一个类应用一个接口,那么这个类里面就必须具备这个接口中的属性class User implements Person {name = 'rose';say() {return 'hi..';}}
接口互相之间也可以进行继承
interface Person {// readonly name: string,name: string,age?: number,[propsName: string]: any,say(): string // 定义一个方法 say , 返回值为字符串}// 表示 Teacher 继承了 Person下面所有属性和方法,并且它还可以有自己的属性和方法interface Teacher extends Person {teach(): string}const setTech = (teacher: Teacher, name: string) => {console.log(person.name);}const obj = {name: 'cos',say() {return 'cos';},teach() { // 这个teach 必须存在否则会报错return 'teach'}}setTech(obj, 'cos')
接口除了可以定义属性和方法之外,自身还可以定义一个函数。
// 这种语法的含义,表示我们在定义一个函数的类型声明,接口能够代表一个函数的类型// 这个函数必须接受一个string类型的参数,并且返回值也是stringinterface sayHi {(word: string): string}const say: SayHi = (word: string) => {return word;}
interface 也可以定义数组这些索引类型。
函数类型和索引类型用的不错。
总结:
interface 和 type 类似但不完全一致, interface 只能定义对象或者函数,type 可以定义基础类型
? // 表示 这个属性可有可无
readonly // 标识该属性只读
[propName: string]: any
say(): string // 定义一个函数,并返回字符串类型
接口可以继承:interface Teacher extends Person {} // 一定有老的东西,也可以有新的东西
接口也可以直接定义一种方法类型:
interface sayHi {
(word: string): string
}
接口其实就是我们在使用ts进行开发的过程中,给我们做语法提示的一个工具。
真正编译成js代码的时候,会把关于接口和类型的代码全部剔除掉。
