TypeScript系列之-- 带你深层次理解对象类型回归本质探究原理

本文主要是介绍TypeScript系列之-- 带你深层次理解对象类型回归本质探究原理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

描述对象的数据类型:

  1. 使用class/constructor描述
  2. 用type或interface描述

使用class/constructor描述

const a: Date = ()=> console.log(1) // Error 会报错缺少日期的一些属性
const a: Function = ()=> console.log(1) // Ok
class Person {   name: string   constructor(name: string) {      this.name = name   }    speak() {    console.log(`${this.name} is speaking`)  }}
const p1 = new Person('lin')      // 新建实例 

interface类型

interface(接口) 是 TS 设计出来用于定义对象类型的,可以对对象的形状进行描述。

定义 interface 一般首字母大写,代码如下:

interface Person {    name: string   age: number}const p1: Person = {    name: 'lin',    age: 18}

注意:属性必须和类型定义的时候完全一致,少写了属性,或多写属性都会报错(interface 不是 JS 中的关键字,所以 TS 编译成 JS 之后,这些 interface 是不会被转换过去的,都会被删除掉,interface 只是在 TS 中用来做静态检查)

可选属性:

跟函数的可选参数是类似的,在属性上加个 ?,这个属性就是可选的,比如下面的 age 属性

interface Person {   name: string   age?: number
}
const p1: Person = {    name: 'lin' }

只读属性:

如果希望某个属性不被改变,可以使用readonly关键字

interface Person {readonly id: number   name: string   age: number
}
let ikun:Person = {id:o,name:"坤坤",age:12
}
ikun.id = 5 // Error 改变这个只读属性时会报错

duck typing(鸭子类型)

事实上,interface 还有一个响亮的名称:duck typing(鸭子类型)

当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。

-- James Whitcomb Riley

interface 的写法非常灵活,它不是教条主义。用 interface 可以创造一系列自定义的类型。只要数据满足了 interface 定义的类型,TS 就可以编译通过

鸭子类型是一个与动态类型( dynamic typing )相关的概念,其中关注的是它定义的方法,而不太关注对象的类型或所属类。当您使用鸭子类型时,你无需做检查类型。相反,您要检查给定方法或属性是否存在

举个例子:

interface FunctionWithProps {   (x: number): number    name: string
}

FunctionWithProps 接口描述了一个函数类型,还向这个函数类型添加了 name 属性,这看上去完全是四不像,但是这个定义是完全可以工作的。

const fn: FunctionWithProps = (x) => {    return x}
fn.name = '哈哈哈哈哈'

事实上, React 的 FunctionComponent(函数式组件) 就是这么写的

interface FunctionComponent<P = {}> {  (props: PropsWithChildren<P>, context?: any):                ReactElement<any, any> | null; propTypes?: WeakValidationMap<P> | undefined;  contextTypes?: ValidationMap<any> | undefined; defaultProps?: Partial<P> | undefined; displayName?: string | undefined;}

FunctionComponent 是用 interface 描述的函数类型,且向这个函数类型添加了一大堆属性

自定义属性(可索引的类型):

有的时候,你不能提前知道一个类型里的所有属性的名字,但是你知道这些值的特征。

这种情况,你就可以用一个索引类型 (index signature) 来描述可能的值的类型

interface RandomKey {    [propName: string]: string
}
const obj: RandomKey = {   a: 'hello', b: 'lin',  c: 'welcome',
}

属性继承:

对接口使用 extends关键字允许我们有效的从其他声明过的类型中拷贝成员,并且随意添加新成员 。

interface Person {  name: string   age: number
}interface Student extends Person {  grade: number
}
//Student 继承了Person声明过的所有类型,并且随意添加新成员
const person:Student = {  name: 'lin',   grade: 100, age:98}//接口也可以继承多个类型
interface Student extends Person ,Student{}

interface 和 class 的关系(implements ):

interface 是 TS 设计出来用于定义对象类型的,可以对对象的形状进行描述。interface 同样可以用来约束 class,要实现约束,需要用到 implements 关键字,implements 是实现的意思,class 实现 interface。

比如一个会干饭的人类

interface Persion {  eatRice(): void
}
class man implements Persion {  eatRice() {console.log('干饭干饭')}//不写这个eatRice方法就会报错  定义了约束后,class 必须要满足接口上的所有条件
}

类也可以被多个接口约束

class KunSon implements A, B {//。。。。
}

约束构造函数和静态属性:使用 implements 只能约束类实例上的属性和方法,要约束构造函数和静态属性,需要这么写

interface Persion {   new (age: number): void  height: number
}
const Man:CircleStatic = class Circle {  static height: 180public son: number  public constructor(age: number) {     this.radius = radius   }
}

implements 语句仅仅检查类是否按照接口类型实现,但它并不会改变类的类型或者方法的类型。一个常见的错误就是以为 implements 语句会改变类的类型——然而实际上它并不会(只有约束class作用):

interface A {x: number;y?: number;
}
class C implements A {x = 0;
}
const c = new C();
c.y = 10;//如上面例子,以往我们鼠标放c上去会显示c的可选类型,但现在什么都没有

Type(类型别名)

类型别名(type aliase),听名字就很好理解,就是给类型起个别名。

type Name = string
const a:Name =  'ikun' // 还是字符串类型tyep FalseLike =  0 | '' | null | undefined | false  // 为false伪类型
type arrItem = number | string   // 联合类型
type StudentAndTeacherList = [Student, Teacher] // 元组类型

Type定义对象类型:

type可以定义对象类型

type Person = {  name: Name 
}

实现继承(交叉类型):

type Student = Person & { grade: number  
} 

type和interface对比

他们俩是完全不同的概念,但网上喜欢拿来对比。。。。(就简单比一下)

  • interface 是接口,相当于类型声明 ,只用来描述一个对象(可以重新赋值)
  • type 只是别名 ,可以描述所有数据类型(不可重新赋值

怎么选择用哪一个??

结论:

  • 对外尽量使用 interface(方便扩展)
  • 对内尽量用type 防止代码分散(保证类型纯真性)
//对外API尽量使用  interface
interface X {name:string
}
interface X {age:number
}
const a:X ={name:'ikun',age:18
} // OK interface会将name和age合并 所以可扩展type Y ={age:number
}
type Y ={name:string
} // Error 这时候报错 不能重复声明Y

参考资料:

类_TypeScript中文文档

https://zhuanlan.zhihu.com/p/489207162

TypeScript: Documentation - Advanced Types

这篇关于TypeScript系列之-- 带你深层次理解对象类型回归本质探究原理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1029806

相关文章

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

Spring Boot 配置文件之类型、加载顺序与最佳实践记录

《SpringBoot配置文件之类型、加载顺序与最佳实践记录》SpringBoot的配置文件是灵活且强大的工具,通过合理的配置管理,可以让应用开发和部署更加高效,无论是简单的属性配置,还是复杂... 目录Spring Boot 配置文件详解一、Spring Boot 配置文件类型1.1 applicatio

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

Java的IO模型、Netty原理解析

《Java的IO模型、Netty原理解析》Java的I/O是以流的方式进行数据输入输出的,Java的类库涉及很多领域的IO内容:标准的输入输出,文件的操作、网络上的数据传输流、字符串流、对象流等,这篇... 目录1.什么是IO2.同步与异步、阻塞与非阻塞3.三种IO模型BIO(blocking I/O)NI

在java中如何将inputStream对象转换为File对象(不生成本地文件)

《在java中如何将inputStream对象转换为File对象(不生成本地文件)》:本文主要介绍在java中如何将inputStream对象转换为File对象(不生成本地文件),具有很好的参考价... 目录需求说明问题解决总结需求说明在后端中通过POI生成Excel文件流,将输出流(outputStre

Python如何查看数据的类型

《Python如何查看数据的类型》:本文主要介绍Python如何查看数据的类型方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录python查看数据的类型1. 使用 type()2. 使用 isinstance()3. 检查对象的 __class__ 属性4.

Python容器类型之列表/字典/元组/集合方式

《Python容器类型之列表/字典/元组/集合方式》:本文主要介绍Python容器类型之列表/字典/元组/集合方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 列表(List) - 有序可变序列1.1 基本特性1.2 核心操作1.3 应用场景2. 字典(D

C#原型模式之如何通过克隆对象来优化创建过程

《C#原型模式之如何通过克隆对象来优化创建过程》原型模式是一种创建型设计模式,通过克隆现有对象来创建新对象,避免重复的创建成本和复杂的初始化过程,它适用于对象创建过程复杂、需要大量相似对象或避免重复初... 目录什么是原型模式?原型模式的工作原理C#中如何实现原型模式?1. 定义原型接口2. 实现原型接口3

JAVA封装多线程实现的方式及原理

《JAVA封装多线程实现的方式及原理》:本文主要介绍Java中封装多线程的原理和常见方式,通过封装可以简化多线程的使用,提高安全性,并增强代码的可维护性和可扩展性,需要的朋友可以参考下... 目录前言一、封装的目标二、常见的封装方式及原理总结前言在 Java 中,封装多线程的原理主要围绕着将多线程相关的操

kotlin中的模块化结构组件及工作原理

《kotlin中的模块化结构组件及工作原理》本文介绍了Kotlin中模块化结构组件,包括ViewModel、LiveData、Room和Navigation的工作原理和基础使用,本文通过实例代码给大家... 目录ViewModel 工作原理LiveData 工作原理Room 工作原理Navigation 工