首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【TypeScript】超详细的笔记式教程!进阶!!【下】

【TypeScript】超详细的笔记式教程!进阶!!【下】

作者头像
HoMeTown
发布于 2022-10-26 00:33:50
发布于 2022-10-26 00:33:50
6950
举报

类型别名

类型别名顾名思义,即字面意思,其实断言也是字面意思,就是断定类型的方法,你说是什么类型就是什么类型,推翻约定,扯远了,继续说类型别名,举个🌰吧:

代码语言:javascript
AI代码解释
复制
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
    if(typeof n === 'string') {
        return n
    } else {
        reutrn n()
    }
}

类型Name其实就是string的别名,类型() => string,一个函数返回一个字符串,这种格式就是类型NameResolverNameOrResolver是一个联合类型,之前说过。

字符串字面量类型

字符串字面量类型,用来约束取值职能是某几个字符串其中的一个字符串,举个🌰:

代码语言:javascript
AI代码解释
复制
type EventSupport = 'click' | 'scroll' | 'mouseEnter'
function handleEvent(ele: Element, event: EventSupport): void {
    // do something
}

handleEvent(document.getElementById('app'), 'scroll') // 完全ok
handleEvent(document.getElementById('app'), 'dbclick') // 完全不ok

元组(Tuple)

元组用来合并不同类型的项,举个🌰:

代码语言:javascript
AI代码解释
复制
let tom: [string,number] = ['tom', 25]

注意:

  • 元组在定义赋值时,你定义的什么类型,初始赋值时,就得添加什么类型的值,必须全部添加完,不能多,也不能少
  • 可以利用下标修改值,但是值必须是相同类型的
  • 元组可以越界,越界的元素只能是你定义元组的时候的联合类型,不能是其他类型,越界的元素不能修改

.. 元组不是很好用,如果你真的不确定你的[]里有啥,其实最好就用let tom: any[] = ['tom', 12]

枚举(Enum)

枚举一般用来做映射,举个栗子:

代码语言:javascript
AI代码解释
复制
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat}

上面这段Ts编译成Js是这样:

代码语言:javascript
AI代码解释
复制
var Days;
(function (Days) {
    Days[Days["Sun"] = 0] = "Sun";
    Days[Days["Mon"] = 1] = "Mon";
    Days[Days["Tue"] = 2] = "Tue";
    Days[Days["Wed"] = 3] = "Wed";
    Days[Days["Thu"] = 4] = "Thu";
    Days[Days["Fri"] = 5] = "Fri";
    Days[Days["Sat"] = 6] = "Sat";
})(Days || (Days = {}));

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

代码语言:javascript
AI代码解释
复制
console.log(Days[0]); // Sun
console.log(Days["Sun"]) // 0

自定义枚举

代码语言:javascript
AI代码解释
复制
enum Days {
  Sun = <any>"Sun",
  Mon = <any>"Mon",
  Tue = <any>"Tue",
  Wed = <any>"Wed",
  Thu = <any>"Thu",
  Fri = <any>"Fri",
  Sat = <any>"Sat",
}
console.log(Days["Sun"]); // Sun

注意:这儿需要使用断言,让tsc无视类型检查

其实在JS在ES6发布之前从来都没有类的概念,都是通过构造函数去模拟类,ES6发布了class,但是大部分Js程序员对类的概念还是比较模糊的,这我解释一下什么是类、对象、OOP、封装、集成、多态、修饰符、抽象类、接口

类的概念

其实可以理解为一件事物的抽象,包含了这个事务的一些属性与方法举个简单的🌰,比如人,人就是一个大类,我们可以抽象出来他的一些特点,比如:这是人的行为,智商情商性别等是人的属性。

对象

对象其实就是类的实例化,是一个抽象,对象就是让他变得现实,一个类可以实例化多个对象,类似我们可以根据这个类,制造很多人。

面向对象 OOP

面向对象开发的三大特性:封装、继承、多态

封装

封装的意思就是我们知道的意思,我们需要通过一些代码实现一个函数,这个函数就是一个封装,再通俗一点说,我们需要实现这个方法,细节呢?我们只需要封装起来,比如先下蹲一点,双腿发力,向上用力等等,把这些细节封装起来,就可以直接调用这个方法进行,同时呢外界也不能直接去修改内部的数据。

继承

子承父业,儿子继承老爹的所有方法&属性,但除了拥有父类所有用的特性外,还有一些别具一格的特性。

多态

由于继承产生了很多相关的不同类,很多儿子继承了同一个老爹,子类对同一个方法可以有不同的响应。比如小王小李都继承老爹老张,但是分别实现了自己getMoney的方法,此时针对一个实例,我们无需了解他是小王还是小李,就可以直接调用getMoney方法,程序会自动判断出来应该如何执行getMoney

修饰符

修饰符是一些关键字,用于限定成员或者类型的性质,比如public表示公有属性or方法

抽象类

抽象类是供其他类继承的基类,抽象类不允许被实例化,抽象类中的抽象方法必须在子类中被实现

接口

不同类之间共有的属性和方法,可以抽象成一个接口,接口可以被类实现,一个类职能继承自另外一个类,但是可以实现多个接口。

ES6中类的用法

类的定义

使用class定义类,使用constructor定义构造函数,通过new生成新实例的时候,会自动调用构造函数。

代码语言:javascript
AI代码解释
复制
class Person {
    public IQ;
    publick name;
    constructor(IQ, name) {
        this.IQ = IQ
        this.name = name
    }
    saySomething() {
        return `hello, im ${this.name}, IQ: ${this.IQ}`
    }
}
let alice = new Person("Alice", 120)
console.log(alice.saySomething())

类的继承

现在有了人的类,我们现在实现一个Cop类,Cop也属于人,也有名字&IQ,子类中用super关键字来调用父类的构造函数与方法:

代码语言:javascript
AI代码解释
复制
class Cop extends Person {
    public job;
    constructor(IQ, name, job) {
        super(IQ, name)
        this.job = job;
    }
    saySomething() {
        return super.saySomething() + 'my job js ${this.job}'
    }
}
let tom = new Cup('tom', 100, 'cop')
console.log(tom.saySomething())

存取器

使用 getter 和 setter可以改变属性的赋值和读取行为:

代码语言:javascript
AI代码解释
复制
class FakerCop extends Person {
    constructor(IQ, name, job) {
        super(IQ, name)
        this.job = job
    }
    get job() {
        return 'fakerCop'
    }
    set job(val) {
        console.log('u want my job is' + value + '?')
    }
}
let tony = new FakerCop("Tony", 200, 'fakerCop');
tony.job = 'realCop'
console.log(tony.job) // fakerCop

静态方法

使用static修饰符修饰的方法成为静态方法,不需要被实例化,直接通过类来调用,举个🌰,定义一个判断真假cop的方法:

代码语言:javascript
AI代码解释
复制
class Cop extends Person {
    public job;
    constructor(IQ, name, job) {
        super(IQ, name)
        this.job = job;
    }
    static isCop(c) {
        return c instanceof Cop;
    }
    saySomething() {
        return super.saySomething() + 'my job js ${this.job}'
    }
}

console.log(Cop.isCop(tom)) // true
console.log(Cop.isCop(tony)) // false

TypeScript中类的用法

public private protected

  • public 修饰的属性或者方法是公有的,可以在任何地方被访问,默认所有的方法和属性都是public
  • private 修饰的属性或者方法是私有的,不能再声明他的类的外部访问
  • protected 修饰的属性或者方法是受保护的,他和private类似,不同的是,它在子类中是可以访问的

public 举个栗子:

代码语言:javascript
AI代码解释
复制
class Animal {
    public name;
    public constructor(name) {
        this.name = name
    }
}

let a = new Animal('Jack')
console.log(a.name) // Jack
a.name = 'Tom'
console.log(a.name) // Tom

private 举个栗子:

代码语言:javascript
AI代码解释
复制
class Animal {
    private name
    public constructor(name) {
        this.name = name
    }
}
let a = new Animal('Jack')
console.log(a.name)
a.name = 'Tom'

ts 会提示属性“name”为私有属性,只能在类“Animal”中访问。

子类中也不能访问,这里就不说了;

protected 举个栗子:

代码语言:javascript
AI代码解释
复制
class Animal {
    protected name;
    public constructor(name) {
        this.name = name
    }
}
class Cat extends Animal {
    constructor(name) {
        super(name);
        console.log(this.name)
    }
}

子类可以访问父类的protected属性

当构造海曙为protected时,这个类只能继承,不能被实例化:

代码语言:javascript
AI代码解释
复制
class Animal {
    protected name;
    protected constructor(name) {
        this.name = name
    }
}

class Cat extends Animal {
    constructor(name) {
        super(name)
    }
}

let a = new Animal('Jack')

参数属性

修饰符和readonly还可以在构造函数参数中使用,等同于类中定义该属性同时给该属性赋值,代码看上去会更简洁:

代码语言:javascript
AI代码解释
复制
class Animal {
    // public name: string;
    public constructor(public name) {
        // this.name = name
    }
}

readonly

只读关键字

代码语言:javascript
AI代码解释
复制
class Animal {
    public constructor(readonly name) {
        
    }
}
let a = new Animal('Jack')
console.log(a.name)
a.name = 'Tony' // Error

需要注意的是,如果readonly与其他修饰符同时出现的时候,需要写在最后,改造上面的栗子:

代码语言:javascript
AI代码解释
复制
class Animal {
    public constructor(public readonly name: string) {}
}

抽象类

abstract 用于定义抽象类和其中的抽象方法,首先抽象类不允许被实例化,举个栗子:

代码语言:javascript
AI代码解释
复制
abstract class Animal {
    public constructor(public name: string) {}
    public abstract sayHi(): void;
}
let a = new Animal('jack')

抛出错误:

其次,抽象类的抽象方法必须被子类实现:

代码语言:javascript
AI代码解释
复制
class Cat extends Animal {
    public eat() {
        console.log()
    }
}

如果不实现sayHi方法,就会抛出错误

正确的做法如下:

代码语言:javascript
AI代码解释
复制
abstract class Animal {
  public constructor(public name: string) {}
  public abstract sayHi(): void;
}

class Cat extends Animal {
  public eat(): void {
    console.log("im eating");
  }
  public sayHi(): void {
    console.log("hi~ my name is " + this.name);
  }
}

let c = new Cat("Jack");
c.eat();
c.sayHi();

类的类型

很简单

代码语言:javascript
AI代码解释
复制
class Animal {
  public constructor(public name: string) {}
  public sayHi(): string {
    return `Hi~ my name is ${this.name}`;
  }
}

let a: Animal = new Animal("Jack");

泛型

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

基本定义

我们实现一个 createArray函数,他可以创建一个指定长度的数组,同事将每一项都填充一个默认值:

代码语言:javascript
AI代码解释
复制
function createArray(length: number, value: any): Array<any> {
    let result = []
    for(let i = 0; i < length; i++) {
        result[i] = value
    }
    return result
}

上面我们用到的是数组泛型,但是any还是有点不妥,我们希望与 value的类型相同,但是我们并不知道value是什么类型,这时候泛型就起作用了:

代码语言:javascript
AI代码解释
复制
function createArray<T>(length: number, value: T): Array<T> {
    let result: T[] = []
    for(let i = 0; i < length; i++) {
        result[i] = value
    }
    return result
}
createArray<string>(3, 'x')

上面的栗子里,我们在函数名后面添加了<T>,其中T用来指代任意输入的类型,在后面输入value: T和输出Array<T>中即可使用了。

接下来的调用中,具体的指定它为string,也可以不指定,交给类型推导

代码语言:javascript
AI代码解释
复制
createArray(3, 'x')

多个类型参数

定义泛型的时候,可以一次定义多个类型参数:

代码语言:javascript
AI代码解释
复制
function swap<T, U>(tup;e: [T, U]): [T, U] {
    return [tuple[1], tuple[0]]
}
swap([7, 'seven']) // ['seven', 7]

泛型约束

函数内部使用泛型变量的时候,我们可能不知道它到底是那种类型,所以不能随意的操作他的属性或者方法:

代码语言:javascript
AI代码解释
复制
function loggingIdentity<T>(arg: T): T {
    console.log(arg.length)
    return arg
}

这样写会抛出错误:

因为泛型T上不一定有length,这时候,我们可以对泛型进行约束,只允许这个函数传入那些包含length属性的变量,这就是泛型约束

代码语言:javascript
AI代码解释
复制
interface lengthwise {
    length: number;
}
function loggintIdentity<T extends lengthwise>(agr: T): T {
    console.log(agr.length)
    return arg
}

这个时候如果你调用loggintIdentity传入的值没有length属性,那么会抛出错误

多个类型参数之间也可以互相约束:

代码语言:javascript
AI代码解释
复制
function copyFields<T extends U, U>(target: T, source: U): T {
  for (const key in source) {
    if (Object.prototype.hasOwnProperty.call(source, key)) {
      target[key] = (<T>source)[key];
    }
  }
  return target;
}
let x = { a: 1, b: 2, c: 3, d: 4 };
console.log(copyFields(x, { b: 10, d: 20 }));

这块可能有同学看不懂target[key] = (<T>source)[key]是啥意思了,我在这解释一下:

(<T>source)[key] === (source as T)[key]

现在的情况是:target的类型是Tsource的类型是U,二者的类型不同,所以无法直接赋值,二者必须断言一个,使他们变成统一类型,如果不这么做,会抛出一个错误:

泛型接口

接口可以约定一个函数的形状:

代码语言:javascript
AI代码解释
复制
interface SearchFunc {
    (source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function (source: string, substring: string) {
    return source.search(subString) !== -1
}

也可以使用有泛型的接口定义函数的形状:

代码语言:javascript
AI代码解释
复制
interface CreateArrayFunc {
  <T>(length: number, value: T): Array<T>;
}
let createArray: CreateArrayFunc;
createArray = function <T>(length: number, value: T): Array<T> {
  let result: T[] = [];
  for (let i = 0; i < length; i++) {
    result[i] = <T>value;
  }
  return result;
};
console.log(createArray(3, "x"));

泛型参数的默认值

代码语言:javascript
AI代码解释
复制
interface CreateArrayFunc {
  <T>(length: number, value: T): Array<T>;
}
let createArray: CreateArrayFunc;
createArray = function <T = string>(length: number, value: T): Array<T> {
  let result: T[] = [];
  for (let i = 0; i < length; i++) {
    result[i] = <T>value;
  }
  return result;
};
console.log(createArray(3, "x"));
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-04-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 秃头开发头秃了 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
TypeScript学习笔记(四)—— TypeScript提高
Type又叫类型别名(type alias),作用是给一个类型起一个新名字,不仅支持interface定义的对象结构,还支持基本类型、联合类型、交叉类型、元组等任何你需要手写的类型。
张果
2022/10/04
2.7K0
TypeScript学习笔记(四)—— TypeScript提高
Typescript学习笔记,从入门到精通,持续记录
TypeScript 最大的优势之一便是增强了编辑器和 IDE 的功能,包括代码补全、接口提示、跳转到定义、重构等。
房东的狗丶
2023/02/17
2.3K0
TypeScript基础常用知识点总结
虽然简介这一部分可能有人会觉得没必要,但是我觉得还是有必要简单的写一下的。我们以后既然要经常用它,当然得从认识它开始啦!不想看就往下滑咯。
害恶细君
2022/11/22
5.6K0
TypeScript基础常用知识点总结
一篇朴实的文章带捋完TypeScript基础,方法是正反对比!
最近在抽出点业余时间学习TypeScript,虽然平时也挺忙的,但是还是想分配些时间出来。掘金这篇文章不错,于是分享给大家。
coder_koala
2019/11/09
1.3K0
TypeScript
TypeScript中的Object类型并不单指普通的对象类型,而是泛指非原始类型,也就是对象,数组和函数
conanma
2021/10/28
2K0
TypeScript 学习笔记(一)
TypeScript 是 JavaScript 的一个超集,主要提供了 类型系统 和对 ES6 的支持,由 Microsoft 开发。 目前应用:vue3.0,angular2.0,vscode, react ....
前端老鸟
2020/05/18
3.1K0
你应该知道的TypeScript高级概念
来源 | https://juejin.cn/post/6897779423858737166
winty
2020/12/07
6200
深度讲解TS:这样学TS,迟早进大厂【17】:类
初学者玩转 TypeScript系列,总计 21 期,点赞、收藏、评论、关注、三连支持! TS系列地址: 21篇文章带你玩转ts
江一铭
2022/09/08
5160
typescript 多继承_说明类的继承和多态有什么作用
对于传统的 JavaScript 程序我们会使用函数和基于原型的继承来创建可重用的组件,但对于熟悉使用面向对象方式的程序员使用这些语法就有些棘手,因为他们用的是基于类的继承并且对象是由类构建出来的。 从 ECMAScript 2015,也就是 ES6 开始, JavaScript 程序员将能够使用基于类的面向对象的方式。 使用 TypeScript,我们允许开发者现在就使用这些特性,并且编译后的 JavaScript 可以在所有主流浏览器和平台上运行,而不需要等到下个 JavaScript 版本。
全栈程序员站长
2022/09/16
1.5K0
typescript 多继承_说明类的继承和多态有什么作用
一起重学TypeScript
class 类名<T> { name!: T; hobby!: T; } # 这样这个类的所有类型为 number let 实例 = new 类名<number>();
程序员海军
2021/10/10
2.3K0
一起重学TypeScript
Typescript真香秘笈
本文由 IMWeb 首发于 IMWeb 社区网站 imweb.io。点击阅读原文查看 IMWeb 社区更多精彩文章。 1. 前言 2018年Stack Overflow Developer的调研(https://insights.stackoverflow.com/survey/2018/)显示,TypeScript已经成为比JavaScript更受开发者喜爱的编程语言了。 之前我其实对于typescript没有太多好感,主要是认为其学习成本比较高,写起代码来还要多写很多类型声明,并且会受到静态类型检查
用户1097444
2022/06/29
6.2K0
Typescript真香秘笈
TypeScript
接口(interface)可以用于对【对象的形状(Shape)】进行描述,当然也可以使用interface 描述 class
九旬
2020/10/23
2.1K0
TypeScript
TS 笔记
子类继承父类,子类可以访问父类公开的属性和方法,但是不能直接获取到父类的私有属性或者受保护的属性
4O4
2022/04/25
5580
TypeScript 超详细入门讲解
当我们需要将 unknown 类型的变量赋值给其他类型的变量的时候,我们可以给他指定类型
小丞同学
2021/10/08
8480
【初学者笔记】🐯年要掌握 Typescript
JavaScript 是弱类型语言, 很多错误只有在运行时才会被发现,而 TypeScript 提供了一套静态检测机制, 可以帮助我们在编译时就发现错误。
一尾流莺
2022/12/10
1.5K0
【初学者笔记】🐯年要掌握 Typescript
TypeScript 终极初学者指南
大家好,我是 ConardLi,在过去的几年里 TypeScript 变得越来越流行,现在许多工作都要求开发人员了解 TypeScript,各大厂的大型项目基本都要求使用 TypeScript 编写。
ConardLi
2022/04/08
7.5K0
TypeScript 终极初学者指南
TypeScript基础知识
在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范。 在程序设计里面,接口起到了一种限制和规范的作用。 接口定义了某一批类所需遵守的规范,接口不必关心这些类的内部状态数据,也不关心这些类里方法的实现细节,它只规定这批类必须提供某些方法,提供这些方法的类就可以满足实际需要。ts中的接口类似java,同时还增加了更灵活的接口类型,包括属性、函数、可索引和类等。
Clearlove
2021/03/04
8400
class 类
抽象类是 TypeScript 中的一种特殊类,它不能直接被实例化,只能被其他类继承或实现。抽象类主要用于定义一些共享的属性和方法,并且可以声明一些抽象方法,这些抽象方法必须在子类中被实现。
程序员王天
2023/10/18
3930
Modern Times
简而言之就是程序之中所有的操作都需要通过对象来完成。一切操作都要通过对象,也就是所谓的面向对象,在程序中对象被分成了两个部分数据和功能,以人为例,人的姓名、性别、年龄、身高等属于数据,人可以说话、走路、吃饭、睡觉这些都属于人的功能,数据在对象中被称为属性,而功能被称为方法,所以简而言之在程序中一切皆对象
冬夜先生
2021/09/22
4860
TypeScript手记(四)
对于传统的 JavaScript 程序我们会使用函数和基于原型的继承来创建可重用的组件,但对于熟悉使用面向对象方式的程序员使用这些语法就有些棘手,因为他们用的是基于类的继承并且对象是由类构建出来的。从 ECMAScript 2015,也就是 ES6 开始, JavaScript 程序员将能够使用基于类的面向对象的方式。使用 TypeScript,我们允许开发者现在就使用这些特性,并且编译后的 JavaScript 可以在所有主流浏览器和平台上运行,而不需要等到下个 JavaScript 版本。
用户7572539
2020/08/26
6660
相关推荐
TypeScript学习笔记(四)—— TypeScript提高
更多 >
交个朋友
加入腾讯云官网粉丝站
双11活动抢先看 更有社群专属礼券掉落
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档