TypeScript - Interfaces(接口)

article/2025/9/25 12:28:00

目录

1、接口介绍

1.1 接口示例

2、可选属性

3、只读属性

4、额外的属性检查

5、函数类型

6、可索引的类型

7、类类型

7.1 类静态部分和实例部分

8、继承接口

9、混合类型

10、接口继承类


1、接口介绍

TypeScript 的核心原则之一是对值所具有的_结构_进行类型检查。 它有时被称做“鸭式辨型法”或“结构性子类型化”。 在 TypeScript 里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。

1.1 接口示例

接口声明是命名对象类型的另一种方法,看下示例:

function people(obj: { name: string, age: number }) {console.log(obj.name+ '年龄是:'+obj.age);
}
let obj = { age: 20, name: '张三', addr: '北京市' }; 
people(obj)// 张三年龄是:20

在这里people方法中,可以传入一个对象,对象必须一个name属性,和一个age属性,就是在传入传参数的时候,如果直接传递的是一个对象,那么这个对象一定是方法声明对象的父集,就是方法people中对象的属性,在传入对象中都能找到,且对应属性类型必须一致。

看另一种写法:

function people(obj: { name: string, age: number }) {console.log(obj.name+ '年龄是:'+obj.age);
}
people({age:20, name: 'z', addr: '北京市'})// 对象字面量只能指定已知属性,并且“addr”不在类型“{ name: string; age: number; }”中。

当然,我们事先定义接口,或者类型别名也是可以的,如下所示:

interface MyInterface {name: string,age: number
}
type MyType = {name: any,age: number,addr: '北京市'
}function people(obj: MyInterface | MyType) {console.log(obj.name+ '年龄是:'+obj.age);
}
let myObj = {age:20, name: '张三', addr: '北京市'}
people(myObj)// 张三年龄是:20

只要MyInterface 和Mytype同时都是name和age属性就可以,因为检查器会逐个检查每个属性是否存在,以及它们对应的类型,类型必须小于等于定义的类型即可。在这里不像其他的面向对象语言,例如:Java,向他们那样必须去实现某个接口,它们这些是编译型语言,在编译的是否会有严格的限制,JavaScript属于解释性语言,限制没那么严格,而TypeScript是JavaScript的超集,自然也遵从这个规定,只要传入的接口或类型别名有对应的属性就行,而这也是TypeScript有时被称做“鸭式辨型法”的原因。

鸭式辨型来自于James Whitecomb Riley的名言:"像鸭子一样走路并且嘎嘎叫的就叫鸭子。

2、可选属性

接口里的属性不全都是必需的。 有些是只在某些条件下存在,或者根本不存在。 可选属性在应用“option bags”模式时很常用,即给函数传入的参数对象中只有部分属性赋值了。

下面是一个示例:

interface MyInterface {name: string,age: numberaddr?: string
}function people(obj: MyInterface) {console.log(obj.name+ '年龄是:'+obj.age);
}
let myObj = {age: 20, name: '张三'}
people(myObj)

可选属性,就是在属性后面加了个问号(?)所以添加问号的属性,都是非必填属性。

可选属性的好处就是可以进行预定义,后续可以根据实际情况去判断该属性是否存在,当然这种方式还有一种好处,在写代码的时候可以自动进行智能提示,找到对应的属性。

如下所示:

 这样也可以防止我们写错属性而没有被发现。

3、只读属性

在声明对象属性的时候,可以在属性名之前添加 readonly 来指定是只读属性。

interface People = {readonly name: string,readonly age: number
}
let p1:People = {name: '张三', age: 12}
p1.age = 24; // 编译报错 无法为“age”赋值,因为它是只读属性。

 对象被重新构建之后,所有的属性都不能变更了。

ReadonlyArray<T>类型,可以保证数组创建之后也不能进行变更了,可读数组类型,实在ES2019(ES10)之后所添加,如下所示:

let numArr:number[] = [10, 30, 50, 70, 90];
let readonlyArr:ReadonlyArray<number> = numArr;
readonlyArr[0] = 123; // 类型“readonly number[]”中的索引签名仅允许读取。
readonlyArr.push(123) // 类型“readonly number[]”上不存在属性“push”
readonlyArr.splice(1); // 属性“splice”在类型“readonly number[]”上不存在
readonlyArr.length = 1  // 无法为“length”赋值,因为它是只读属性。
numArr = readonlyArr  // 不能分配给可变类型 "number[]"

4、额外的属性检查

在对象中指定了可选属性,如果传入的是一个对象字面量,而这个对象字面量中的属性,和之前对象定义的属性不一致时,会编译报错,说对象字面量只能指定已知的属性。

例如:那属性name写成names时,如下所示:

interface MyInterface {name?: string,age?: numberaddr?: string}function people(obj: MyInterface) {console.log(obj.name+ '年龄是:'+obj.age);}people({age: 20, names: '张三'})// 类型“{ age: number; names: string; }”的参数不能赋给类型“MyInterface”的参数。

如果跳过编译检查,有以下两种方式:

  // 第一种方式,使用类型断言people({age: 20, names: '张三'} as MyInterface)// 第二种方式,把字面量对象赋值给一个变量。let obj = {age: 20, names: '张三'}people(obj)

第二种方式,虽然能跳转编译检查,但可能会产生bug,虽然能运行,但是结果会与预期不一样,所以,最好能提前规避,在编译期间找出对应的bug.

如果我们确定对象可能会有多个未知的属性,我们可以添加字符串索引签名,类似于在JavaScript函数,传参一般(...obj),说明该函数接收的参数可能还有其他多个。

interface MyInterface {name?: string,age?: number,addr?: string,[other:string]: any
}

5、函数类型

我们可以使用接口表示函数类型,参数属性和之前对象属性定义一样,末尾再加上函数的返回类型,如下所示:

interface MyInterface {(name: string, age: number, addr?:string) :string}let p1:MyInterface;  
p1 = function(name:string, age:number, addr?:string) {return name+ '年龄是:'+age
}
console.log('p1: ', p1("张三", 20));

对象函数参数定义和JavaScript中一样,名字不一定要和接口里定义的一样,函数中的参数,与传参顺序有关,所以在这里,实际传的值与函数参数顺序对应起来就可以了。

如果函数中没有指定参数类型,会根据接口定义进行自动推断。

interface MyInterface {(name: string, age: number, addr?:string) :string}let p1:MyInterface;  
p1 = function(a, b, addr) {return a+ '年龄是:'+b
}
console.log('p1: ', p1("张三", 20));

6、可索引的类型

我们可以使用索引访问类型在另一种类型上查找特定属性:

type Person = { age: number; name: string; alive: boolean };
let p1: Person;
p1= {age: 10, name: '张三', alive: true}
console.log('Person["age"]: ', p1["age"]);
// Person["age"]:  10     

索引类型本身就是一个类型,因此我们可以完全使用联合、 或其他类型的类型:keyof

type Person = { age: number; name: string; alive: boolean };// type I1 = string | number
type I1 = Person["age" | "name"];     // type I2 = string | number | booleantype I2 = Person[keyof Person];type AliveOrName = "alive" | "name";
// type I3 = string | boolean
type I3 = Person[AliveOrName];

如果您尝试为不存在的属性编制索引,您甚至会看到错误:

type Person = { age: number; name: string; alive: boolean };// 编译报错,类型“Person”上不存在属性“alve”。
type I1 = Person["alve"];

用于获取数组元素的类型,我们可以将其方便地捕获数组对应的元素类型:number typeof

const MyArray = [{ name: "Alice", age: 15 },{ name: "Bob", age: 23 },{ name: "Eve", age: 38 },];// type Person = {
//     name: string;
//     age: number;
// }  
type Person = typeof MyArray[number];// type Age = numbers
type Age = typeof MyArray[number]["age"];     
// Or
type Age2 = Person["age"];

只能在索引时使用类型,这意味着不能使用 进行变量引用:const

const key = "age";
//报错,类型“key”不能作为索引类型使用。
type Age = Person[key];
// 可以
type Age1 = Person['age'];

用类型别名是可以的。

type key = "age";
// 可以 type Age = number
type Age = Person[key];

7、类类型

C#或Java里接口的基本作用一样,TypeScript也能够用它来明确的强制一个类去符合某种契约。也就是面对对象编程中类的继承概念,定义一个接口,由类去实现这个接口。

interface animal {birthday: DategetInfo(): string
}class Cat implements animal {birthday: Date;name: string;getInfo() :string {return this.name + ", " + this.birthday;}constructor(name: string, birthday: Date) {this.name = name;this.birthday = birthday;}
}let c1 = new Cat('叮当猫', new Date('2023-05-09'));console.log(c1.getInfo());// 叮当猫, Tue May 09 2023 08:00:00 GMT+0800 (China Standard Time)

7.1 类静态部分和实例部分

在操作类和接口的时候,当你用构造器签名去定义一个接口并试图定义一个类去实现这个接口时会得到一个错误:

interface Animal {birthday: Datenew(name: string, birthday: Date) 
}
// 编译错误,类型“Cat”提供的内容与签名“new (name: string, birthday: Date): any”不匹配。
class Cat implements Animal {birthday: Date;name: string;getInfo() :string {return this.name + ", " + this.birthday;}constructor(name: string, birthday: Date) {this.name = name;this.birthday = birthday;}
}

所以,在类的静态部分我们做一些改变,我们再增加一个接口AnimalInter,然后把原接口构造器添加一个返回值为AnimalInter接口,新建一个函数,函数的返回类型为AnimalInter接口,而函数的第一个参数进行实例化,如下图所示:

interface Animal {new(name: string, birthday: Date): AnimalInter 
}interface AnimalInter {getInfo() : string
}function CreateFunc(first:Animal, name: string, birthday: Date ):AnimalInter {return new first(name, birthday)
}class Cat{ birthday: Date;name: string;getInfo() {return this.name + ", " + this.birthday;}constructor(name: string, birthday: Date) {this.name = name;this.birthday = birthday;}
}let result = CreateFunc(Cat, '张三', new Date('2023-02-09'))
console.log('result: ', result.getInfo());

这样在示例化这个Cat类的时候,检查是否和Animal接口构造函数定义的一致。

8、继承接口

接口的继承和类是一样的,是可以相互继承的,这样可以进行拆分多个接口,便于以后的可复用,重构起来也更方便,如下所示:

interface Animal {name: string,
}interface AnimalInter extends Animal {getInfo() : string
}class Cat implements AnimalInter{ birthday: Date;name: string;getInfo() {return this.name + ", " + this.birthday;}constructor(name: string, birthday: Date) {this.name = name;this.birthday = birthday;}
}let result = new Cat('张三', new Date('2023-02-09'))
console.log('result: ', result.getInfo());

一个接口可以继承多个接口,创建出多个接口的合成接口。

interface Animal {name: string,
}
interface AnimalSecond {age: number,
}interface AnimalInter extends Animal, AnimalSecond {getInfo() : string
}class Cat implements AnimalInter{ birthday: Date;name: string;age: number;getInfo() {return this.name + ", " + this.birthday + ", age: "+this.age;}constructor(name: string, birthday: Date, age: number) {this.name = name;this.birthday = birthday;this.age = age;}
}let result = new Cat('张三', new Date('2023-02-09'), 20)
console.log('result: ', result.getInfo());

9、混合类型

混合类型,一个变量它的类型可能有多个,number | string| boolean 等,一个对象也可能是,以下就是一个对象,还可以是一个函数。

interface Animal {(age: number): string;name: string;time: number;
}function getAnimal (): Animal {let animal = function(age: number) {} as Animalreturn animal;
}
let getResult = getAnimal();
getResult(20);
getResult.time = 20;
// 报错,无法为“name”赋值,因为它是只读属性。函数的name,是可读的
getResult.name = '张三';
console.log(getResult.time);
console.log(getResult.name ); 

10、接口继承类

接口继承类时,会继承类的成员,不包括对应的实现。接口可以继承类的私有成员,和受保护的成员,如果需要继承这个接口,只能由接口继承类的子类继承。在构造器函数中,子类的构造函数必须包含 "super" 的调用。

class AnimalClass {private name: any;
}interface AnimalInterface extends AnimalClass{getName(): string; 
}class Animal extends AnimalClass implements AnimalInterface{getName() {return '123';};constructor() {super();}
}// 类型 "Cat" 中缺少属性 "name",但类型 "AnimalInterface" 中需要该属性。
class Cat implements AnimalInterface {getName() {return ''}
}let anima = new Animal()

Animal类继承AnimalClass类,在构造器中,必须调用super() 方法,子类进行初始化的时候,父类中有定义成员属性也需进行初始化操作,而AnimalInterface接口只能被AnimalClass类的子类所实现,因为本身接口就继承了AnimalClass类,而Cat在实现AnimalInterface接口时,必须包含接口从其他类中继承的所有属性,包括私有属性,Cat类不是AnimalInterface接口继承类的子类,所以就报错了,而父类私有属性不能通过子类实例化后的对象进行直接访问,也不会被继承。


http://chatgpt.dhexx.cn/article/GRGTUgEj.shtml

相关文章

type 与 interface

type 与 interface 官方文档是这么说的&#xff1a; For the most part, you can choose based on personal preference, and TypeScript will tell you if it needs something to be the other kind of declaration. If you would like a heuristic, use interface until you…

TypeScript中type和interface区别

typescript中interface介绍&#xff1a;TypeScript 中的接口 interface_疆~的博客-CSDN博客通常使用接口&#xff08;Interface&#xff09;来定义对象的类型。https://blog.csdn.net/qq_40323256/article/details/128478749 type type关键字是声明类型别名的关键字。用来给一…

TypeScript中interface 与 type的区别,你真的懂吗?

在写 ts 相关代码的过程中&#xff0c;总能看到 interface 和 type 的身影。它们的作用好像都一样的&#xff0c;相同的功能用哪一个都可以实现&#xff0c;也都很好用&#xff0c;所以也很少去真正的理解它们之间到底有啥区别&#xff0c; 分别在什么场景下使用&#xff0c;将…

Android 设置字体的三种方法(TypeFace)

http://blog.csdn.net/legend12300/article/details/69875816 Android系统默认字体支持四种字体&#xff0c;分别为&#xff1a; noraml &#xff08;普通字体,系统默认使用的字体&#xff09;sans&#xff08;非衬线字体&#xff09;serif &#xff08;衬线字体&#xff09;…

Android 之 Paint API —— Typeface (字型)

本节带来Paint API系列的最后一个API&#xff0c;Typeface(字型)&#xff0c;由字义&#xff0c;我们大概可以猜到&#xff0c;这个 API是用来设置字体以及字体风格的&#xff0c;使用起来也非常的简单&#xff01;下面我们来学习下Typeface的一些相关 的用法&#xff01; 官方…

Pycham_python 安装 gherkin

1.File>Settings>Plusings> 在MarketPlace标签下&#xff0c;搜索gherkin&#xff0c;选择如下图所示&#xff0c;点击Install&#xff0c;安装成功后重启pycharm即可 2&#xff0c;打开feature文件&#xff0c;就会有格式显示了 转载于:https://www.cnblogs.com/aide…

学Selenium自动化需要知道的之Python测试框架

根据StackoverFlow网站的开发者调查&#xff0c;Python是2019年增长最快的编程语言。在整体排名中&#xff0c;它甚至超越了Java&#xff0c;排在第二位&#xff0c;成为最受喜爱的编程语言之一。 Python流行的几个原因之一是对测试自动化框架的广泛支持。大多数流行的Python框…

机器学习框架Chainer学习

chainer优势——边定义边运行 当下已有的深度学习框架使用的是“定义后运行”机制。即意味着&#xff0c;首先定义并且固化一个网络&#xff0c;再周而复始地馈入小批量数据进行训练。由于网络是在任何前向、反向计算前静态定义的&#xff0c;所有的逻辑作为数据必须事先嵌入网…

Jenkins - Hello World

开始 Jenkins 的第一行代码 无论学哪种语言&#xff0c;都是从 hello world 开始&#xff0c;因为这个学会了&#xff0c;就说明你已经从入门到精通了。 让我们来看看 Jenkins 的 hello world 吧 0. 登录 Jenkins 1. 新建 item 2. 创建一个 Freestyle project 3. 增加执行命令…

Cucumber--基于vue前端的自动化测试(四)

cucumber是BDD (Behavior-driven development&#xff0c;行为驱动开发)的一个自动化测试的副产品。它使用自然语言来描述测试&#xff0c;使得非程序员可以理解他们。Gherkin是这种自然语言测试的简单语法&#xff0c;而Cucumber是可以执行它们的工具。 cucumber本质上是使用根…

【Jenkins】【Jenkins 使用】Jenkins 与 Git

【文章末尾给大家留下了大量的福利】 1、概述 Jenkins 与 Git 的结合使用&#xff0c;可以理解为是 Jenkins 的一个强大之处。为什么要这么说&#xff0c;简要说明一下这个工作模式就能理解&#xff1a; 一个软件项目&#xff0c;开发过程中通常都会使用到一些源码管理工具&am…

SSH and GPG keys

问题&#xff1a;gitgithub.com: Permission denied (publickey). fatal: Could not read from remote repository. gitgithub.com&#xff1a;权限被拒绝&#xff08;publickey&#xff09;。 我相信很多程序员开始都会对Git比较陌生。但是用过几次&#xff0c;就会觉得Git的功…

自动化测试工具Cucumber的简单介绍

背景介绍 随着测试的发展&#xff0c;测试自动化越来越成为人们的关注点。 现在我们公司也在进行接口自动化的推广&#xff0c;在我看来接口自动化的价值就在于整体项目的回归&#xff0c;完成一些没法通过人力进行的测试&#xff0c;比如压力测试。 为了解决测试开发人员和…

【Jenkins】学习笔记

学习笔记 一、Jenkins1.1、Jenkins的作用 二、下载安装2.1、安装环境2.2、安装GitLab2.3、安装Jenkins 三、Jenkins Git Maven 部署配置3.1、安装maven插件3.2、新建项目3.3、自动发布到测试服务器 四、publish over ssh 配置4.1、超时机制4.2、shell的日志输出4.3、运行前清…

快速了解KEGG

我们有时候很关心基因所在的pathway、上下调控以及一堆基因富集到的pathway&#xff0c;再或者同源基因等信息&#xff0c;KEGG数据库也算是目前&#xff08;注释&#xff09;常用的明星数据库 KEGG&#xff1a;京都基因和基因组百科全书&#xff1a;KEGG项目于1995年5月在日本…

【Jenkins基础知识学习笔记】

文章目录 1、Master/Slave架构2、搭建步骤3、工作流程4、配置建议5、通信方式参考文档 1、Master/Slave架构 Jenkins采用Master/Slave架构&#xff0c;Master/Slave相当于Server和agent的概念&#xff0c;Master提供web接口让用户来管理Job和Slave&#xff0c;Job可以运行在Ma…

Gherkin语法详解之Scenario outline(四)

如果我想要对于不同的数据集&#xff0c;重复一个场景的所有步骤?这是一个数据驱动测试的经典案例。这将通过使用一个场景大纲来实现

BDD - BDD Automation Framwork 自动化框架

BDD - BDD Automation Framwork 自动化框架 引言BDD 测试框架Jenkins 集成Framework Components 框架组件IDEs 集成开发环境NotepadEclipseJetBrains IntelliJ IDEAMicrosoft Visual Studio 引言 BDD 自动化框架使得 QA 工程师很容易将 Gherkin Scenarios 转换成自动化测试用例…

zipkin

zipkin zipkin为分布式链路调用监控系统&#xff0c;聚合各业务系统调用延迟数据&#xff0c;达到链路调用监控跟踪。 architecture 如图&#xff0c;在复杂的调用链路中假设存在一条调用链路响应缓慢&#xff0c;如何定位其中延迟高的服务呢&#xff1f; 日志&#xff1a; 通…