美文网首页TypeScriptTypeScript
TS学习笔记(二):接口

TS学习笔记(二):接口

作者: 半掩时光 | 来源:发表于2019-05-10 14:23 被阅读0次

在面向对象语言中,接口(Interfaces)是一个很重要的概念,它是对行为的抽象,而具体如何行动需要由类(classes)去实现(implements),TypeScript 中的接口除了可用于对类的一部分行为进行抽象以外,也常用于对对象的形状(Shape)进行描述。

接口初探

类型检查器不会去检查属性的顺序,只要相应的属性存在并且类型也是对的就可以。

interface IPerson{
  name: string;
  age: number
}
function say(person: IPerson): void {
  console.log(`my name is ${person.name}, and age is ${person.age}`)
}
let me = {
  name: 'funlee',
  age: 18
}
say(me); // my name is funlee, and age is 18

可选属性

定义可选属性的接口,只需在可选属性名字的定义后面加一个 ? 符号

interface IPerson {
  name: string;
  age: number;
  love?: string
}
function say(person: IPerson): void {
  if(person.hasOwnProperty('love')) {
    console.log(`my name is ${person.name}, my age is ${person.age}, and I love ${person.love}`);
  } else {
    console.log(`my name is ${person.name}, and age is ${person.age}`);
  }
}
let me = {
  name: 'funlee',
  age: 18,
  love: 'TS'
}
let you = {
  name: 'Jack',
  age: 18
}
say(me); // my name is funlee, my age is 18, and I love TS
say(you) // my name is Jack, and age is 18

只读属性

定义只读属性的接口,只需在只读属性名前加 readonly

interface IPerson {
  readonly name: string;
  age: number;
  love?: string
}
let me: IPerson = {
  name: 'funlee',
  age: 18
}
me.name = 'new name'; // error!

额外的属性检查

当一个对象字面量里声明了接口中不存在的属性时,会报不存在错误,即使该属性已设置为可选属性,因为该对象字面量会被特殊对待而且会经过额外属性检查,绕开额外属性检查的方法如下:

  • 使用类型断言
  • 添加一个字符串索引签名,前提是你能够确定这个对象可能具有某些做为特殊用途使用的额外属性
  • 将该对象赋值给另一个变量
// 错误写法,会进行额外检查
interface IPerson {
  name: string;
  age?: number;
}
let me: IPerson = {
  name: 'funlee',
  love: 'TS'
}

// 方法一:类型断言
interface IPerson {
  name: string;
  age?: number;
}
let me = {
  name: 'funlee',
  love: 'TS'
} as IPerson

// 方法二:字符串索引签名
interface IPerson {
  name: string;
  age?: number;
  [propName: string]: any;
}
let me: IPerson = {
  name: 'funlee',
  love: 'TS'
}

// 方法三:赋值给另一个变量
interface IPerson {
  name: string;
  age?: number;
}
let me = {
  name: 'funlee',
  love: 'TS'
}
let you: IPerson = me;

函数类型

接口可以描述函数类型,它定义了函数的参数列表和返回值类型,参数列表里的每个参数都需要名字和类型,函数的参数名不需要与接口里定义的名字相匹配,只需要类型兼容就可以了。

let getArea: (width: number, height: number) => number = (w: number, h: number): number =>{
  return w * h;
}
console.log(getArea(5, 6)) // 30

可索引的类型

接口可以描述那些能够通过索引得到的类型,可索引类型具有一个索引签名,它描述了对象索引的类型,还有相应的索引值类型,索引签名支持两种类型:number 和 string,但是由于 number 实际上会被转化为 string 类型(根据对象 key 的性质),所以需要遵守:number 索引的返回值类型是 string 索引的返回值类型的子类型。

interface IPerson {
  [index: string]: string;
}
let me: IPerson = {love: 'TS'}
me.name = 'funlee';
me.age = 18; // error

如果 interface 里还声明了一个和索引签名索引返回值类型不匹配的属性,会报错

interface ITest {
  [index: string]: string;
  name: string;
  age: 18; // 报错,因为返回值类型是number,不符合string类型
}

还可以声明一个 readonly 的索引签名

interface IPerson {
  readonly [index: string]: string;
}
let p: IPerson = {name: 'funlee'};
p.love = 'TS'; // error

类类型

typescript 里也允许像 Java、C# 那样,让一个 class 去实现一个 interface;但是需要注意的是,接口描述的是类的公共部分,而不是公共和私有两部分,所以不会检查类是否具有某些私有成员。

interface ISome {
  prop: string // 描述一个属性
  method(paramA: string, paramB: number) // 描述一个方法
}
class A implements ISome {
  prop: 'propValue'
  method(a: string, b: number) {
    // ...
  }
  constructor(paramA: number){
    // ...
  }
}

静态部分与实例部分

首先看一个示例:用构造器签名定义一个接口,并试图实现这个接口:

interface Person {
  new(name: string)
}
class People implements Person {
  constructor(name: string) {
    // ...
  }
}
// 报错:no match for the signature 'new (name: string): any'.

这是因为:当类实现一个接口时,只对实例部分进行类型检查,而constructor存在于静态部分,所以不在检查的范围内。
所以做法如下:

// 针对类构造函数的接口
interface CPerson {
  new(name: string)
}
// 针对类的接口
interface IPerson {
  name: string
  age: number
}
function create(c: CPerson, name: string): IPerson {
  return new c(name)
}
class People implements IPerson {
  name: string
  age: number
}
let p = create(People, 'funlee') // 可以

继承接口

和类一样,接口也可以相互继承,如:

interface Shape {
  color: string;
}
interface Square extends Shape {
  sideLength: number;
}
const square = <Square>{};
square.color = 'blue';
square.sideLength = 10;

同时,一个接口也可以继承多个接口,创建出多个接口的合成接口,如:

interface Shape {
  color: string;
}
interface PenStroke {
  penWidth: number;
}
interface Square extends Shape, PenStroke {
  sideLength
}
const square = <Square>{};
square.color = 'blue';
square.sideLength = 10;
square.penWidth = 5.0;

混合类型

允许让一个对象同时作为函数和对象使用,并带有额外的属性,如:

interface MixedDemo {
  (str: string): void;
  defaultStr: string;
}

function foo(): MixedDemo {
  let x = <MixedDemo>function(str: string){
    console.log(str)
  }
  x.defaultStr = 'Hello, world'
  return x
}

let c = foo();
c('This is a function') // 'This is a function'
console.log(c.defaultStr) // 'Hello, world'

接口继承类

接口可以继承自一个类,从而像声明了所有类中存在的成员,并且private和protected成员也会被继承,这意味着:只有类自己或子类能够实现该接口,例子如:

class A {
  protected propA: string
}
interface I extends A {
  method(): void
}

// 下面这种做法会报错
class C implements A {
  // 因为propA是类A的保护成员,只有自身和子类可实现
  // 但类C不是A的子类
  protected propA: string
  method() {}
}

// 下面这种做法则是允许的
class C extends A implements A {
  protected propA: string
  method() {}
}

相关文章

  • TS学习笔记(二):接口

    在面向对象语言中,接口(Interfaces)是一个很重要的概念,它是对行为的抽象,而具体如何行动需要由类(cla...

  • Typescript

    TypeScript(TS)部分 TypeScript学习笔记

  • 【第7篇】TypeScript泛型的案例代码详解

    1、最简单泛型例子 Ts代码 Js文件 2、泛型类型与接口 Ts代码一 Ts编译js代码一 Ts代码二 Ts编译j...

  • TS笔记之 接口

    接口 介绍 TypeScript 的核心原则之一是对值所具有的结构进行类型检查。 它有时被称做“鸭式辨型法”或“结...

  • 8、TypeScript 接口继承接口,类实现多接口

    1、ts类中只能继承一个父类2、ts类中可以实现多少接口,使用(,)号分隔3、ts接口中可以继承多个接口,使用(,...

  • TypeScript基础入门 - 接口 - 继承接口

    转载地址 TypeScript基础入门 - 接口 - 继承接口 项目实践仓库 为了保证后面的学习演示需要安装下ts...

  • 2019-10-16

    https://ts.xcatliu.com/introduction/get-typescript 学习笔记 入...

  • TS接口

    函数和方法的区别: 当一个函数是对象的属性时,这个函数为该对象的方法 接口就是用代码描述一个对象必须有什么属性(包...

  • TS: 接口

    接口算是官方文档里的第一个知识点了,这篇文章会简单介绍 TypeScrip 里的接口。 类型 在说接口之前我们先来...

  • TS - 接口

    接口是对行为的抽象,由类来定义对象或函数的类型 初始化 tslint 配置规则 可选属性 A red tomato...

网友评论

    本文标题:TS学习笔记(二):接口

    本文链接:https://www.haomeiwen.com/subject/mclaoqtx.html