接口
ts的核心原则之一就是对值所具有的结构进行类型检查
接口的作用就是为类型命名和代码定义规则
//基础使用
interface Person1 {
name: string,
age: number
}
let p1: Person1 = {
name: '张三',
age: 18
}
可选属性
在使用这个接口时,可选属性可以定义也可以不用定义,可选属性可以对可能存在的属性进行预定义;
interface Person2 {
name: string,
age: number,
sex?: string
}
//sex不声明也不会报错
let p2: Person2 = {
name: '李四',
age: 18
}
let p3: Person2 = {
name: '李四',
age: 18,
sex: '男'
}
只读属性
readonly 只允许在刚定义时修改值
interface ReadonlyPerson {
readonly name: string,
age: number
}
let readonlyPerson: ReadonlyPerson = {
name: '张三',
age: 20
}
//readonlyPerson.name = '李四', //error 设置了readOnly 不能够对属性的值进行修改
readonlyPerson.age = 24 // ok
在ts中 有readonlyArray类型 与array相似,但是把所有可变方法都去掉了,以确保数组不会发生改变
不可以直接赋值到普通数组, 可以用类型断言进行重写
let list: ReadonlyArray = [1, 2, 3];
函数类型接口
对于函数类型接口,函数的参数名不需要于接口里定义的名字相匹配,类型相同即可
interface FunInterface { //这种写法为整个接口只有一个函数类型
(name: string, age: number): string //()内为参数类型 :string为函数返回值类型
}
let consolePerson: FunInterface = function (name: string, age: number): string { //这里函数的参数类型可以不写
return `姓名${name},年龄${age}`
}
interface FunInterface2 { //这种写法是一个对象
consoleInfo(name: string, age: number): string
}
let consoleInfo: FunInterface2 = {
consoleInfo: function (name, age) {
return `姓名${name},年龄${age}`
}
}
可索引的类型
interface StringArray { // 字符串类型的数组
[index: number]: string
}
let myArray: StringArray = ['1', '2', '3']; //数组的索引是number index改为string就会报错
let myObject: StringArray = {
1: '1', 2: '2'
}
//ts支持两种类型的索引,字符串和数字,数字索引的返回值的类型必须是字符串索引返回值类型的子类型
class Animal {
name: string
constructor(name: string) {
this.name = name
}
}
class Dog extends Animal {
constructor(name: string) {
super(name)
}
}
interface MoreIndexInterface {
[index: number]: Dog,
[index: string]: Animal
}
let moreIndexInterfaceList: MoreIndexInterface = {
dog: new Dog('狗'),
animal: new Animal('动物')
}
interface NumberDictionary {
[index: string]: number;
length: number; // 可以,length是number类型
// name: string // 错误,`name`的类型与索引类型返回值的类型不匹配
}
let numberDictionary: NumberDictionary = {
a: 5,
length: 333
}
类类型接口
实现接口 ts能够用它明确的强制一个类去符合某种契约
interface realizationClass {
name: string,
age: number,
sayHello(name: string, age: number): string
}
// 类中有两个类型,一个是实例中类型,一个为静态类型,接口只约束实例中类型 挂载在prototype的方法
class ClassPerson implements realizationClass {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name
this.age = age
}
//即使写了这个方法,仍然会报错,因为实例中类型没有符合接口的约束
static sayHello(name: string, age: number): string {
return `年龄为${age}的${name}对你打招呼`
}
sayHello(name: string, age: number): string {
return `年龄为${age}的${name}对你打招呼`
}
}
继承接口
和类一样 ,接口也可以进行继承;
一个接口可以继承多个接口
interface ParentInterface {
name: string
}
interface ChildInterface extends ParentInterface {
age: number
}
interface PersonInfoInterface {
info: ChildInterface
}
let p4: PersonInfoInterface = {
info: {
age: 18,
name: '张三'
}
}
混合类型
接口要求既要是传入string类型参数返回string类型数据的函数,又要是一个拥有age属性的对象
interface MixInterface {
(name: string): string,
age: number
}
let a = function (): MixInterface {
let fn = <MixInterface>function (name: string) {
return `${name}在给你打招呼`
}
fn.age = 18;
return fn;
}
let b = a();
console.log(b.age);
console.log(b('小狗'));
接口继承类
当接口继承了一个类类型时,它会继承类的成员但不包括其实现
会继承private和protected成员
class Control { //这个类定义了一个string类型的state属性
state: string
constructor(state: string) {
this.state = state
}
}
//该接口约束
// {
// state:string,
// select():void
// }
interface SelectableControl extends Control { //这个接口继承了类, 即state属性 ,又新增了一个select方法
select(): void
}
class Button extends Control implements SelectableControl { //button类先继承了control类 满足了state属性,
constructor(state: string) {
super(state)
}
select(): void { } //手动写select() 规则就满足
}