TypeScript学习笔记(7)-接口

什么是接口?

可以使用接口来描述对象、命名和参数化对象的类型,以及将现有的命名对象类型组成新的对象类型。简单说就是 描述变量类型的。

示例:

// 定义接口
interface Person {
    firstName: string;
    lastName: string;
    fullName(): string;
}

//声明 Person类型的变量
let wdk: Person = {
    firstName: 'w',
    lastName: 'dk',
    fullName(): string {
        return this.firstName + ' ' + this.lastName
    }
}

console.log(wdk.fullName()) // 输出 "w dk"

wdk.firstName=100; //提示 不能将类型“number”分配给类型“string”。

接口在编译时可以验证参数,属性类型 以及返回类型确保可以编译成功,而不用等运行时发现错误。

使用接口的原因:

  1. 类型检查,避免错误。

  2. 使开发保存一致性,因为实现接口的每个对象都在相同的类型定义下运行。

  3. 描述现有的 JavaScript API 并阐明函数参数和返回类型。可以清楚的知道 Api 传入和返回类型。

interface (接口)与 type (类型别名) 有何不同?

  1. 语法上 type 后面有  =,interface 没有;
  2. type 可以描述任何类型组合,interface 只能描述对象结构;
  3. interface 可以继承自(extends)interface 或对象结构的 type。type 也可以通过  &  做对象结构的继承;
// interface 继承
interface Shape {
    x: number;
    y: number;
  }

  // 继承扩展
  interface Square extends Shape {
    width: number;
    height: number;
  }

  const rect: Square= { x: 0, y: 0, width: 0, height: 0 };


//type 继承
type Shape = {
    x: number;
    y: number;
}

type Square = Shape & { r: number }

const circle: Square = { x: 0, y: 0, r: 8 }
  1. 多次声明的同名 interface 会进行声明合并,type 则不允许多次声明;
  • 4.1 同名属性的不能进行类型覆盖修改,类型必须完全一致 x 必须为 number
//同名属性的不能进行类型覆盖修改,类型必须完全一致 x必须为number

// interface 支持声明合并,文件下多个同名的 interface,它们的属性会进行合并
interface Square {
    x: number;
}

interface Square {
    // 后续属性声明必须属于同一类型。属性“x”的类型必须为“number”,但此处却为类型“string | number”。ts(2717)
    x: string | number;
    y: number;
}
const square: Square = { x: 10, y: 30 };
  • 4.2 extends 可以将属性的类型进行收窄,比如从 string | number 变成 string
// extends 可以将属性的类型进行收窄,比如从 string | number 变成 string
// 父级
interface Shape {
    x: string | number;
    y: number;

}

interface Square extends Shape {
    x: number;
    area(): number;
}

let squareArea: Square = {
    x: 10,
    y: 10,
    area(): number {
        return this.x * this.y;
    }
}

console.log(squareArea.area())
  • 4.3 type 则不允许多次声明。
// type 不支持声明合并,一个作用域内不允许有多个同名 type
// 报错:标识符“Square”重复。
type Square = {
    x: number;
}

// 报错:标识符“Square”重复。
type Square = {
    y: Square;
}

声明和实例化接口规范

  1. interface 关键字开头
  2. 接口名称不能是类型系统中预定义的类型名称之一
  3. 接口名称为 PascalCase 形式(帕斯卡命名法)
  4. 定义该接口的属性(或成员)及其类型。属性可以为必需、可选或只读属性
属性类型 说明 示例
必须 除非另行指定,否则所有属性都是必需的。 firstName: string;
可选 在属性名称的末尾添加问号 (?)。对于不是必需的属性,请使用此属性。这可以防止类型系统在省略该属性时引发错误。 firstName?: string;
只读 在属性名称的前面添加 readonly 关键字。对于只应在首次创建对象时修改的属性,请使用此属性。 readonly firstName: string;
  • 实现 厨师在 做饭 烹饪 烤面包   一个接口:
// 王大可是大厨
interface Chef {
    name: string;
    fat?: boolean;
    prepareMeal(): void;
    bake(): void;
    cook(): void;
}

// 实现接口
const chef: Chef = {
    name: "王大可",
    prepareMeal: function () {
        console.log(this.name + " 正在准备菜肴...");
    },
    bake: function () {
        console.log(this.name + " 正在烤面包...");
    },
    cook: function () {
        console.log(this.name + " 正在烹饪菜肴...");
    }
};

chef.prepareMeal(); // 输出 "王大可 正在准备菜肴..."
chef.bake(); // 输出 "王大可 正在烤面包..."
chef.cook(); // 输出 "王大可 正在烹饪菜肴..."


//定义可选属性 是否肥胖
interface MichelinThree extends Chef {
    name: string;
    prepareMeal(): void;
    bake(): void;
    cook(): void;
}

const michelinThree: MichelinThree = {
    name: "米其林三星-张三",
    prepareMeal: function () {
        console.log(this.name + " 正在准备菜肴...");
    },
    bake: function () {
        console.log(this.name + " 正在烤面包...");
    },
    cook: function () {
        console.log(this.name + " 正在烹饪菜肴...");
    }
};

michelinThree.prepareMeal(); // 输出 "米其林三星 正在准备菜肴..."

创建可索引类型

interface MyInterface {
    [index: number]: string;
}
const myArray: MyInterface = ["a""b""c"];
console.log(myArray[0]); // 输出a

使用接口描述 JavaScript API

可以使用接口描述现有的 JavaScript API 并阐明函数参数和返回类型。接口使你能够清楚地了解 API 的期望值和返回值。

const fetchURL = 'https://jsonplaceholder.typicode.com/posts'
interface Post {
    userId: number;
    id: number;
    title: string;
    body: string;
}

// 定义一个异步函数,用于获取指定URL的帖子
async function fetchPosts(url: string) {
    // 使用fetch函数获取指定URL的响应
    let response = await fetch(url);
    // 使用json函数将响应体转换为json格式
    let body = await response.json();
    // 返回转换后的json格式的帖子数组
    return body as Post[];
}

// 定义一个异步函数,用于显示帖子
async function showPost() {
    // 使用fetchPosts函数获取指定URL的帖子
    let posts = await fetchPosts(fetchURL);
    // 获取帖子数组中的第一个帖子
    let post = posts[0];
    // 打印帖子的id
    console.log('Post #' + post.id)
    // 打印帖子的作者,如果作者id为1,则打印管理员,否则打印作者id
    console.log('Author: ' + (post.userId === 1 ? "Administrator" : post.userId.toString()))
    // 打印帖子的标题
    console.log('Title: ' + post.title)
    // 打印帖子的内容
    console.log('Body: ' + post.body)
}
// 调用showPost函数
showPost();

知识检查

  1. 接口的主要工作是什么?
  • 描述对象的属性和返回类型。

    2.  当省略接口中的属性时,如何防止类型系统引发错误?

  • 将属性设置为可选属性。

    3.  用另一个接口扩展一个接口会发生什么情况?

  • 必须从所有接口实现所有必需的属性。

  1. 思考 为什么下面这句话不对?
  • 如果属性具有完全相同的名称,则多个接口可以具有相同的属性。
// 继承时 属性名称相同 但是类型不同无法继承 但是可以收窄继承
interface A {
    x:number;
}
interface B extends A{
    x:string;
}

// 接口“B”错误扩展接口“A”。
//   属性“x”的类型不兼容。
//     不能将类型“string”分配给类型“number”。


原文始发于微信公众号(王大可996):TypeScript学习笔记(7)-接口

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/205225.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!