Published on

TypeScript - Interface

Authors
  • avatar
    Name
    Deng Hua
    Twitter

目录

Introducing Interface

Interfaces serve almost the exact same purpose as type aliases (with a slightly different syntax). We can use them to create reusable, modular types that describe the shapes of objects

接口的作用几乎与类型别名完全相同(语法略有不同)。我们可以使用它们来创建可重复使用的模块化类型,以用于描述对象。

interface Person {
  name: string
  age: number
}

const sayHappyBirthday = (person: Person) => {
  return `Hey ${person.name}, congrats on turning ${person.age}!`
}

sayHappyBirthday({ name: 'Jerry', age: 42 })

Readonly and Optional Interface Properites

可选属性

如果对象的某个属性将是可选的,可以使用?将其属性注释:

interface Person {
  first: string
  last: string
  nickname?: string
}

const thomas: Person = {
  first: 'Thomas',
  last: 'Hardy',
}

只读属性

使用readonly关键字在其属性名前注释

interface Person {
  readonly id: number
  first: string
  last: string
  nickname?: string
}

const thomas: Person = {
  id: 1,
  first: 'Thomas',
  last: 'Hardy',
  nickname: 'Tom',
}

thomas.id = 2; // ❌ 无法为“id”赋值,因为它是只读属性。

对只读属性的重复赋值将会报错

Interface Methods

描述对象的方法

interface Person {
  readonly id: number
  first: string
  last: string
  nickname?: string
  //
  sayHi: () => string
  // 另一种语法
  sayHello(): string
}

const thomas: Person = {
  id: 1,
  first: 'Thomas',
  last: 'Hardy',
  nickname: 'Tom',
  //
  sayHi: () => 'hi',
  sayHello: () => 'hello',
}

Interface Method Parameters

描述对象方法的参数

interface Product {
  name: string
  price: number
  applyDiscount: (discount: number) => number
  // or
  anotherApplyDiscount(discount: number): number
}

const shoes: Product = {
  name: 'Blue Suede Shoes',
  price: 100,
  applyDiscount(amount: number) {
    return 1
  },
  // or
  anotherApplyDiscount: (amount: number) => {
    return 2
  },
}

Reopening Interfaces

在已经实现的接口上,拓展新的属性。这是Interface独有的特性

type Person = {
  name: string
}
type Person = { // ❌ 标识符“Person”重复
  age: number
}


interface Dog {
  name: string
  age: number
}
interface Dog {
  breed: string
  bark: () => string
}

const elton: Dog = {
  name: 'Elton',
  age: 0.5,
  breed: 'Australian Shepherd',
  bark() {
    return 'WOOF!'
  },
}

Extending Interfaces

Interface的另一个特性是,可以继承另一个接口。

假设我们需要一个新的ServiceDog接口,还是使用上面的示例:

/* You don't need to do this.

  interface ServiceDog {
    name: string
    age: number
    // rewrite......
  }
*/

// using extends syntax
interface ServiceDog extends Dog {
  // now, ServiceDog Automatically contain the required attributes in the Dog interface
  job: 'drug sniffer' | 'bomb' | 'guide dog'
}

const chewy: ServiceDog = {
  name: 'chewy',
  age: 1,
  breed: 'Lab',
  bark() {
    return 'WOOF!'
  },
  //Newly added
  job: 'drug sniffer',
}

Interface Multiple Inheritance

接口的多重继承

interface Human {
  name: string
}
interface Employee {
  readonly id: number
  email: string
}
interface Engineer extends Human, Employee {
  level: string
  languages: string[]
}

const john: Engineer = {
  name: 'john',
  id: 1,
  email: 'john@email.com',
  level: 'senior',
  languages: ['Java', 'JavaScript'],
}

Interface Vs. Type Alias

  1. Interface只能描述对象
type Color = 'red' | 'blue' // ✅

interface Color // ❌ you can't using interface describe

不能用Interface替换所有的Type,如果不描述对象,则必须使用类型别名。

  1. Interface可以拓展,Type Alias不允许

Reopening Interfaces

  1. Interface可以继承,Type Alias不允许
interface Name {
  name: string
}
interface Person extends Name {
  age: number
}

const person: Person = {
  name: 'Jerry',
  age: 42,
}

Type Alias要实现继承,可以使用交叉类型

type Name = {
  name: string
}
type Person = Name & {
  age: number
}

const person: Person = {
  name: 'Jerry',
  age: 42,
}