一、接口初探

  • 有时候我们传入的参数可能会包含很多的属性,但是编译器只会检查那些必须的属性是否存在,以及类型是否匹配,而咱们要讲的接口其实就是用来描述下面这个例子里的结构,对于接口传入的数据咱们只关心它的外形,只关心他传入的对象是够满足咱们接口的限定条件,满足咱们就认定他是正确的
function Animal(config: {name: string, age: number}) {
console.log("我叫:" + config.name + "今年" + config.age + "岁了")
}
console.log(Animal({ name: "yxl", age: 24 }))
// 下面重构
interface Config {
name: string
age: number
}
function Animal(config: Config) {
console.log("我叫:" + config.name + "今年" + config.age + "岁了")
}
/*
* 这里把接口限制的类型付给了变量myAnimal,即使咱们传入了接口中没有限制的属性,
* 这里编译之后也不会出现报错,是因为接口类型检查不会对变量赋值进行检查
* 如果咱们这里把Animal({name: "yxl", age: 24, color: "黑色的头发"})这样传参的话,
* 接口类型检查会报出当前color属性没有在Config接口中进行限制,所以是不被允许的
*/
let myAnimal = { name: "yxl", age: 24, color: "黑色的头发" }
console.log(Animal(myAnimal))

二、可选属性

  • 接口里的属性有时候不是必须的,有的咱们可以用到,有的 用不到,这个时候可选属性接口就是一个不错的选择,可选属性的好处就是咱们可以对可能存在的属性进行预先定义,其次是能够捕获不存在属性是的一个错误
interface Config {
name: string
age?: number
// [propName: string]: any 字符串索引签名
}
function Animal(config: Config) {
console.log("我叫:" + config.name + "今年" + config.age + "岁了")
}
/*
* 这里将Animal传参中的age咱们故意打错了个字母,这个时候你就会发现当前接口会对这个属性进行检查
* 接口会对当前ages报错,不存在于当前接口规范中,这个时候为了避免这种报错可以采用类型断言,告诉这个接口,
* 当前穿的参数就是你的规范,这个时候可以发现错误消失了,还有另一种方法是通过索引签名的方式进行屏蔽错误
* [propName: string]: any 这个索引签名就是为了你能够预见某个对象可能觉有某些特殊的用途而准备的。
*/
console.log(Animal({ name: "yxl", ages: 24 } as Config))

三、只读属性

  • 一些对象属性只能在对象刚刚创建的时候修改其值。 你可以在属性名前用 readonly 来指定只读属性:
interface Point {
readonly x: number
readonly y: number
}
let p:Point = { x: 12, y: 14 }
p.x = 15 // 错误
/*
* TypeScript 具有 ReadonlyArray<T> 类型,它与 Array<T> 相似,只是把所有可变方法去掉了,
* 因此可以确保数组创建后再也不能被修改:
*/
let a: number[] = [1, 2, 3]
let aa: ReadonlyArray<number> = a
aa[0] = 14; // Index signature in type 'readonly number[]' only permits reading.
aa.push(4) // Property 'push' does not exist on type 'readonly number[]'.
aa.length = 10 // Cannot assign to 'length' because it is a read-only property.
a = aa as number[] // 类型断言为数字组成的数组
a[0] = 15

四、函数类型

  • 接口能够描述JavaScript中对象拥有的各种各样的外形。除了描述带有属性的普通对象外,接口也可以描述函数类型。接下来我们一起看一下函数类型接口是怎么使用的
interface SearchFun {
(source: string, subString: string): Boolean
}
let mySearch: SearchFun // @1
/*
* 这里对声明了一个匿名函数,并且将这个匿名函数付给了变量mySearch,并且同时
* 给这个匿名函数进行了传参,当然这个传参遵循了SearchFun接口规范,
* 接口会自动推断参数的类型,因为咱们已经将mySearch函数付给了SearchFun类型变量
* 注意: 函数类接口不同于属性类接口,要求属性的变量相同,这里变量可以不同,只需要保证变量的类型为string就行
* function(a, b): Boolean
* mySearch = function (a, b): Boolean { 这个方案也可,因为@1中已经将函数付给了接口类型变量
* */
mySearch = function (source: string, subString: string): Boolean {
let result = source.search(subString);
return result > -1
}
console.log(mySearch("http://b28.sy.souyoung.com/ad/cpcAuction", "28")) // true

五、可索引类型

  • TypeScript 支持两种索引签名:字符串和数字。 可以同时使用两种类型的索引,但是数字索引的返回值必须是字符串索引返回值类型的子类型。 这是因为当使用 number 来索引时,JavaScript 会将它转换成string 然后再去索引对象。 也就是说用 100(一个 number)去索引等同于使用'100'(一个 string )去索引,因此两者需要保持一致。接下来看看如何使用:
/*
* 第一种情况数字类型索引NumberArr的时候返回值是string 这个时候调用a[0] 得到了Bob
* [index: number]: string
* 第二种情况是字符串索引NumberArr的时候返回值是string or number,这个时候
* 返回值是string调用:a["name"] 得到了Bob 返回值是number调用:a["name"] 得到
* 了数字:1
* [index: string]: string
* let a: NumberArr = {
* "name": "Bob"
* }
* * [index: string]: number
* let a: NumberArr = {
* "age": 24
* }
* */
interface NumberArr {
[index: number]: string
}
let a: NumberArr = ["Bob", "Jerry"] // 可
// let a: NumberArr = [55, 66] 不可
console.log(a[0]) // 可
class Animal {
name: string
}
class Dog extends Animal {
breed: string
}
interface NotOkay {
[x: string]: Animal // Numeric index type 'Animal' is not assignable to string index type 'Dog'.
[y: number]: Dog
}
/*
* 上边的例子很好的诠释了两种索引类型可以同时使用,但是这两者又必须
* 遵循之间的规则,那就是数字索引的返回值必须是字符串索引返回值类型的子类型
* 上边Animal并不是Dog的子类型,刚好弄反了,所以咱们在运行编译的时候会
* 报错。下面是正确的使用方式
* interface NotOkay {
* [x: string]: Animal
* [y: number]: Dog
* }
* 下面的例子是对类进行了约束
* */
interface Animal {
// 定义类的name属性值
name: string;
// 定义类中的方法
eat(name: string, gender: string): void
}
class Dog implements Animal {
name: string;
constructor(name: string){
this.name = name;
};
// 注意接口定义的方法有参数,当你不传也不会报错
eat() {
console.log("defind success")
}
}
var dog = new Dog("pika")
dog.eat()
class Cat implements Animal {
name: string;
constructor(name: string){
this.name = name;
};
eat(name: string, gender: string) {
console.log(`${this.name} is ${gender} cat like eat ${name}`)
}
}
var cat = new Cat("herry")
cat.eat("fish", "male")
/*
* 接口描述了类的公共部分,而不是私有跟公共两部分,他不会帮你检查类是够具有某些私有成员。
* 当一个类去实现一个接口的时候,他只会对其实例部分进行检查。constructor存在于类的静态部分,所以不再检查范围内。
*/

六、接口继承

  • 和类一样,接口也可以相互继承。 这让我们能够从一个接口里复制成员到另一个接口里,可以更灵活地将接口分割到可重用的模块里。下面是实际应用的例子一起看一下:
interface Animal {
name: string
say(): void
}
interface Person extends Animal {
work(): void
closer: string
}
class Progremmer implements Person {
closer: string;
name: string;
say(): void {
console.log(`${this.name}说我喜欢穿${this.closer}`)
}
work(): void {
console.log(`${this.name}说工作使我快乐!!!`)
}
constructor(name: string, closer: string) {
this.name = name;
this.closer = closer;
}
}
let g:Person = new Progremmer("小明", "花衣服")
g.say();
g.work();
/*
* 上边中的接口继承了接口,就意味着person这个接口有了Animal的属性以及方法
* 这个时候咱们定义的程序员类去实现这个Person,实现这个person接口就意味着类必须实现
* 这个接口中的方法跟属性,上述例子有体现
*/

七、混合类型

  • 接口能够描述 JavaScript 里丰富的类型。 因为 JavaScript 其动态灵活的特点,有时你会希望一个对象可以同时具有上面提到的多种类型。
interface Counter {
(start: number): string
name: string
say(str: string): void
}
/*
* 声明一个接口,如果只有(start: number): string一个成员,那么这个接口就是函数接口,
* 同时还具有其他两个成员,可以用来描述对象的属性和方法,这样就构成了一个混合接口。
*/
function myCounter(): Counter {
function counter(start: number): string {
return ""
}
/*
* function counter实现了接口的描述,成为了一个函数,因为myCounter是Counter类型* 的,所以counter还具有name属性跟say方法
*/
counter.name = "yxl"
counter.say = function (str: string) {
console.log(`我要学习${str}`)
}
let myCounters: Counter = counter
return myCounters
}
let s = myCounter();
s(10);
s.name= "sss";
s.say("TypeScript");
/*
* 官方文档这里使用了类型断言
* function counter(): Counter {
* let myCounters = (function (start: number) { }) as Counter
* myCounters.name = "yxl"
* myCounters.say = function (str: string) {
* console.log(`我要学习${str}`)
* }
* return myCounters
* }
*/

Interface(接口分享)第一节的更多相关文章

  1. 第一节 如何用Go实现单链表

    一.概念介绍 下面这副图是我们单链表运煤车队. 每节运煤车就是单链表里的元素,每节车厢里的煤炭就是元素中保存的数据.前后车通过锁链相连,作为单链表运煤车,从1号车厢开始,每节车厢都知道后面拉着哪一节车 ...

  2. Ext JS学习第十六天 事件机制event(一) DotNet进阶系列(持续更新) 第一节:.Net版基于WebSocket的聊天室样例 第十五节:深入理解async和await的作用及各种适用场景和用法 第十五节:深入理解async和await的作用及各种适用场景和用法 前端自动化准备和详细配置(NVM、NPM/CNPM、NodeJs、NRM、WebPack、Gulp/Grunt、G

    code&monkey   Ext JS学习第十六天 事件机制event(一) 此文用来记录学习笔记: 休息了好几天,从今天开始继续保持更新,鞭策自己学习 今天我们来说一说什么是事件,对于事件 ...

  3. 第一节:《线程安全和锁Synchronized概念》

    第一节:线程安全和锁Synchronized概念 一.进程与线程的概念 (1)在传统的操作系统中,程序并不能独立运行,作为资源分配和独立运行的基本单位都是进程. 在未配置 OS 的系统中,程序的执行方 ...

  4. 我的第一节Android课

    我的第一节安卓课程,今天非比寻常的一天,我开始了我程序猿之路的第一节安卓课程,安卓课程只是我的一个兴趣班,我的本专业是java开发,因为喜欢做一个属于自己的一个手机APP,就选多个一样技能,毕竟十八般 ...

  5. 第四章 跨平台图像显示库——SDL 第一节 与SDL第一次亲密接触

    http://blog.csdn.net/visioncat/article/details/1596576 GCC for Win32 开发环境介绍(5) 第四章 跨平台图像显示库——SDL 第一节 ...

  6. seajs第一节,seajs基本使用

    什么是seajs,它是干什么使用的,可以去网上搜索一下, 官网:http://seajs.org/docs/ 基本使用seajs <!DOCTYPE html> <html> ...

  7. VUE2.0实现购物车和地址选配功能学习第一节(来源--慕课网河畔一角)

    第一节  vue知识 vue-resource:和后台交互的一个插件,实现get.post和jsonp等功能.(替代jQuery) vue特点: 1.易用:通过创建vue实例,{{}}绑定数据十分方便 ...

  8. go interface接口

    一:接口概要 接口是一种重要的类型,他是一组确定的方法集合. 一个接口变量可以存储任何实现了接口方法的具体值.一个重要的例子就是io.Reader和io.Writer type Reader inte ...

  9. 第一节:.Net版基于WebSocket的聊天室样例

    一. 说在前面的话 该篇文章为实时通讯系列的第一节,基于WebSocket编写了一个简易版聊天样例,主要作用是为引出后面SignalR系列的用法及其强大方便之处,通过这个样例与后续的SignalR对比 ...

  10. 第一节:ASP.NET开发环境配置

    第一节:ASP.NET开发环境配置 什么是ASP.NET,学这个可以做什么,学习这些有什么内容? ASP.NET是微软公司推出的WEB开发技术. 2002年,推出第一个版本,先后推出ASP.NET2. ...

随机推荐

  1. swoole父进程和子进程之间通信的例子

    <?php /** 这是一个swoole父进程和子进程之间通信的例子 */ //进程创建成功后回调处理 function handle(swoole_process $worker){ //从进 ...

  2. 基于Python的接口自动化实战-基础篇之读写配置文件

    引言 在编写接口自动化测试脚本时,有时我们需要在代码中定义变量并给变量固定的赋值.为了统一管理和操作这些固定的变量,咱们一般会将这些固定的变量以一定规则配置到指定的配置文件中,后续需要用到这些变量和变 ...

  3. centos7虚拟机时间和本地时间相差8小时

    安装ntp和ntpdate 在安装centos7虚拟机的时候,已经将时区设置为了Asia/shanghai,但还是出现时间不准,相差了8小时 可以安装ntp和ntpdate,使用 NTP 公共时间服务 ...

  4. 【C语言教程】“双向循环链表”学习总结和C语言代码实现!

    双向循环链表 定义 双向循环链表和它名字的表意一样,就是把双向链表的两头连接,使其成为了一个环状链表.只需要将表中最后一个节点的next指针指向头节点,头节点的prior指针指向尾节点,链表就能成环儿 ...

  5. kafka-消费者测试

    1. 在窗口1创建一个producer,topic为test,broker-list为zookeeper集群ip+端口   /usr/local/kafka/bin/kafka-console-pro ...

  6. spring boot:在项目中引入第三方外部jar包集成为本地jar包(spring boot 2.3.2)

    一,为什么要集成外部jar包? 不是所有的第三方库都会上传到mvnrepository, 这时我们如果想集成它的第三方库,则需要直接在项目中集成它们的jar包, 在操作上还是很简单的, 这里用luos ...

  7. kubernetes:用kubeadm管理token(kubernetes 1.18.3)

    一,token的用途: 1,token是node节点用来连接master节点的令牌字串, 它和ca证书的hash值是把一台node节点加入到kubernetes集群时要使用的凭证 2, 通过kubea ...

  8. Jira 8.5.1 安装教程

    Jira安装教程 一.CentOS设置 1. 更换阿里源 curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/rep ...

  9. C++学习---二叉树的输入及非递归遍历

    二叉树的二叉链表存储表示如下 //二叉树的二叉链表存储表示 typedef struct BiTNode { char data;//结点数据域 struct BiTNode* lchild, * r ...

  10. dubbo配置加载优先级

    优先级从高到低: JVM 启动 -D 参数优先,这样可以使用户在部署和启动时进行参数重写,比如在启动时需改变协议的端口: XML 次之,如果在 XML 中有配置,则 dubbo.properties ...