阅读 122

TypeScript 原始类型、函数、接口、类、泛型 基础总结

原始数据类型

原始数据类型包括:

  • Boolean

  • String

  • Number

  • Null

  • undefined

类型声明是TS非常重要的一个特点,通过类型声明可以指定TS中变量、参数、形参的类型。

  • Boolean 类型

    let boolean: boolean = true boolean = false boolean = null // bollean = 123  报错不可以将数字 123 赋值给 boolean类型的变量 复制代码

  • Number 类型

    //ES6 Number 类型 新增支持2进制和8进制 let num: number = 123 num = 0b1111  复制代码

  • String 类型

    let str1: string = 'hello TS' let sre2: string = `模板字符串也支持使用 ${str1}`] 复制代码

  • Null 和 Undefined

    let n: null = null let u: undefined = undefined n = undefined u = null // undefined 和 null 是所有类型的子类型 所以可以赋值给number类型的变量 let num: number = 123 num = undefined num = null 复制代码

any 类型

any  表示队变量没有任何显示,编译器失去了对 TS 的检测功能与 JS 无异(不建议使用)。

let notSure: any = 4 // any类型可以随意赋值 notSure = `任意模板字符串` notSure = true notSure = null // 当 notSure 为any 类型时,在any类型上访问任何属性和调用方法都是允许的, 很有可能出现错误 notSure.name // 现在调用name属性是允许的,但很明显我们定义的notSure没有name这个属性,下面的调用sayName方法也是如此 notSure.sayName() 复制代码

array 类型

// 数组类型,可以指定数组的类型和使用数组的方法和属性 let arrOfNumbers: number[] = [1, 2, 3] console.log(arrOfNumbers.length); arrOfNumbers.push(4) 复制代码

tuple 元组类型

// 元组类型  元组就是固定长度,类型的数组   // 类型和长度必须一致 let u: [string, number] = ['12', 12] // let U: [string, number] = ['12', 12, true]   报错信息为:不能将类型“[string, number, boolean]”分配给类型“[string, number]”。源具有 3 个元素,但目标仅允许 2 个。 // 也可以使用数组的方法,如下所示push一个值给元组u u.push(33) 复制代码

Interface 接口

  • 对对象的形状(shape)进行描述

  • Duck Typing(鸭子类型)

interface Person {     // readonly id 表示只读属性的id不可以修改     readonly id: number;     name: string;     age: number;     // weight? 表示可选属性,可以选用也可以不选用     weight?: number } let host: Person = {     id: 1,     name: 'host',     age: 20,     weight: 70 } //host.id = 2 报错 提示信息为:无法分配到 "id" ,因为它是只读属性 复制代码

function 函数类型

// 方式一:函数声明的写法   z 为可选参数 , function add1 (x: number, y: number, z?: number): number {     if (typeof z === 'number') {         return x + y + z     } else {         return x + y     } } // 需要注意的是:可选参数必须置于所有必选参数之后,否则会报错 add1(1, 2, 3) // 方式二:函数表达式 const add2 = (x: number, y: number, z?: number): number => {     if (typeof z === 'number') {         return x + y + z     } else {         return x + y     } } // 使用interface接口  描述函数类型 interface ISum {     (x: number, y: number, z?: number): number } let add3: ISum = add1 复制代码

值的注意的是:可选参数必须置于所有必选参数之后,否则会报错,如下图展示的错误案例所示:·

image-20211120152558241

类型推论

当定义变量时没有指定类型,编译器会自动推论第一次赋的值为默认类型

let s = 'str' // s = 12  本句将会报错,提示为:不能将类型“number”分配给类型“string” 复制代码

联合类型

使用 | 分隔可选类型

let StringOrNumber: string | number StringOrNumber = 123 StringOrNumber = '111' 复制代码

类型断言

使用 as 关键字进行类型断言

function getLength (rod: number | string): number {     const str = rod as string     //这里我们可以用 as 关键字,告诉typescript 编译器,你没法判断我的代码,但是我本人很清楚,这里我就把它看作是一个 string,你可以给他用 string 的方法。     if (str.length) {         return str.length     } else {         const num = rod as number         return num.toString().length     } } 复制代码

类型守卫

// 4.类型守卫 type guard     typescript 在不同的条件分支里面,智能的缩小了范围 function getLength2 (rod: number | string): number {     if (typeof rod === 'string') {         return rod.length     } else {         // else 里面的rod 会自动默认为number类型         return rod.toString().length              } } 复制代码

Class 类

面向对象编程的三大特点:

  • 封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,

  • 继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性。

  • 多态(Polymorphism):由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。

话不多少,看代码:

class Animal {     readonly name: string     constructor(name: string) {         this.name = name         console.log(this.run())     }     // private run ():私有的    protected run () 受保护的     run () {         return `${this.name} is running`     } } const animal = new Animal('elephant') // console.log(animal.name) animal.run() //elephant is running // 继承 class Dog extends Animal {     age: number     constructor(name, age) {         super(name)         console.log(this.name)         this.age = age     }     bark () {         console.log(`这只在叫的狗狗叫${this.name},它今年${this.age}岁了`)     } } const dog = new Dog('旺财', 5) dog.run() // 旺财 is running dog.bark() // 这只在叫的狗狗叫旺财,它今年5岁了 // 多态 class Cat extends Animal {     static catAge = 2     constructor(name) {         super(name)         console.log(this.name) // 布丁     }     run () {         return 'Meow,' + super.run()     } } const cat = new Cat('布丁') console.log(cat.run()) // Meow,布丁 is running console.log(Cat.catAge) // 2 复制代码

class中还提供了readonly关键字,readonly为只读属性,在调用的时候不能修改。如下所示:

image-20211124155826105

类成员修饰符

  • public修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是public的。

  • private修饰的属性或方法是私有的,不能在声明它的类的外部访问。

    上述示例代码中,在父类Animalrun 方法身上加上private修饰符之后就会产生如下图的报错信息:

    image-20211124154129377

  • protected 修饰的属性或方法是受保护的,它和private类似,区别在于它在子类中也是可以访问的。

上述示例代码中,在父类Animalrun 方法身上加上protected修饰符之后就会产生如下图的报错信息:

image-20211124153823828

接口和类

类可以使用 implements来实现接口。

// interface可以用来抽象验证类的方法和方法 interface Person {     Speak (trigger: boolean): void; } interface Teenagers {     Young (sge: number): void } // 接口之间的继承 interface PersonAndTeenagers extends Teenagers {     Speak (trigger: boolean): void; } // implements 实现接口 class Boy implements Person {     Speak (mouth: boolean) { } } // class Girl implements Person, Teenagers 和  class Girl implements PersonAndTeenagers 作用相同 class Girl implements PersonAndTeenagers {     Speak (mouth: boolean) { }     Young (sge: number) { } } 复制代码

enum枚举

枚举成员会被赋值为从 0 开始递增的数字,同时也会对枚举值到枚举名进行反向映射:

enum Color {     red = 'red',     blue = 'blue',     yellow = 'yellow',     green = 'green' } // 常量枚举 const enum Color {     red = 'red',     blue = 'blue',     yellow = 'yellow',     green = 'green' } console.log(Color.red) // 0 // 反向映射 console.log(Color[0]) // red const value = 'red' if (value === Color.red) {     console.log('Go Go Go ') 复制代码

  • 常量枚举经过编译后形成的js文件如下:

image-20211124182628644

  • 非常量枚举经过编译器编译之后的js文件如下:

image-20211124182633413

Generics 泛型

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。

  • 约束泛型

  • 类与泛型

  • 接口与泛

示例代码如下:

function echo (arg) {     return arg } let result1 = echo(123) // 参数传递123后result1 的类型为any // 泛型 function echo2<T> (arg: T): T {     return arg } let result2 = echo2(123)  // 加上泛型之后  参数传递 123后result2的类型为number function swap<T, U> (tuple: [T, U]): [U, T] {     return [tuple[1], tuple[0]] } console.log(swap(['hero', 123]))//[ 123, 'hero' ] // 约束泛型  interface IWithLength {     length: number } function echoWithLength<T extends IWithLength> (arg: T): T {     console.log(arg.length)     return arg } const str = echoWithLength('123') const obj = echoWithLength({ length: 3, name: 'Tom' }) const arr = echoWithLength([1, 2, 3, 4]) // 类与泛型 class Queue<T> {     private data = []     push (item: T) {         return this.data.push(item)     }     pop (): T {         return this.data.shift()     } } const queue = new Queue<number>() queue.push(1) console.log(queue.pop().toFixed())// 1 // 接口与泛型  interface KeyPair<T, U> {     key: T     value: U } let kp1: KeyPair<string, number> = { key: 'str', value: 123 } let kp2: KeyPair<number, string> = { key: 123, value: 'str' } let arr2: Array<string> = ['1', '2'] // 使用 Array<string> 等价于 interface Array<T> 复制代码

类型别名 type-alias

类型别名,就是给类型起一个别名,让它可以更方便的被重用。

let sum: (x: number, y: string) => number const result1 = sum(1, '2') // 将(x: number, y: string) => number类型取一个别名 为 PlusType type PlusType = (x: number, y: string) => number let sum2: PlusType const result2 = sum2(2, '2') type StrOrNum = string | number let result3: StrOrNum = 123 result3 = '123' 复制代码

字面量

let Name: 'name' = 'name' // Name = '123' //报错信息:不能将类型“"123"”分配给类型“"name"” let age: 19 = 19 type Directions = 'Up' | 'Down' | 'Left' | 'Right' let up: Directions = 'Up' 复制代码

交叉类型

// 交叉类型  使用 ‘&’ 符号进行类型的扩展 interface IName {     name: string } type IPerson = IName & { age: number } let person: IPerson = { name: 'Tom', age: 19 } 复制代码

内置类型

  • 全局对象

// global objects 全局对象 const a: Array<string> = ['123', '456'] const time = new Date() time.getTime() const reg = /abc/ // 此时reg为RegExp类型 reg.test('abc') 复制代码

  • build-in object 内置对象

    Math.pow(2, 2) //返回 2 的 2次幂。 console.log(Math.pow(2, 2)) // 4 复制代码

  • DOM  and  BOM

    // document 对象,返回的是一个 HTMLElement let body: HTMLElement = document.body // document 上面的query 方法,返回的是一个 nodeList 类型 let allLis = document.querySelectorAll('li') //当然添加事件也是很重要的一部分,document 上面有 addEventListener 方法,注意这个回调函数,因为类型推断,这里面的 e 事件对象也自动获得了类型,这里是个 mouseEvent 类型,因为点击是一个鼠标事件,现在我们可以方便的使用 e 上面的方法和属性。 document.addEventListener('click', (e) => {     e.preventDefault() }) 复制代码

  • utility types实用类型

    interface IPerson2 {     name: string     age: number } let viking: IPerson2 = { name: 'viking', age: 20 } // partial,它可以把传入的类型都变成可选 type IPartial = Partial<IPerson> let viking2: IPartial = {} // Partial 将IPerson 中的类型变成了可选类型 所以 viking2 可以等于一个空对象 // Omit,它返回的类型可以忽略传入类型的某个属性 type IOmit = Omit<IPerson2, 'name'> // 忽略name属性 let viking3: IOmit = { age: 20 } 复制代码

如果加上name属性将会报错:不能将类型“{ age: number; name: string; }”分配给类型“IOmit”。对象文字可以只指定已知属性,并且“name”不在类型“IOmit”中。

 伪原创工具 SEO网站优化  https://www.237it.com/

作者:不一213
链接:https://juejin.cn/post/7035563509882552334

文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐