当前位置:首页 » 《随便一记》 » 正文

TypeScript入门学习之路_牛先森家的博客

26 人参与  2022年05月18日 11:09  分类 : 《随便一记》  评论

点击全文阅读


TypeScript学习之路

    • TypeScript学习之路
      • 安装typescript环境
      • typescript起步
      • typescript开发工具vscode自动编译.ts文件
      • typescript中的数据类型
      • typescript中的函数
      • typescript中类的定义
      • 继承
        • javascript中的继承
        • typescript中的继承
      • typescript类的静态属性和静态方法
      • typescript类的多态
      • typescript的抽象类
      • typescript中的接口
      • typescript中的泛型

TypeScript学习之路

安装typescript环境

npm install -g typescript

查看版本

tsc -v

typescript起步

1、新建hello.ts

const hello : string = "Hello World!"
console.log(hello)

2、通过 tsc 命令编译

tsc hello.ts 

3、此时路径下会生成一个hello.js文件

var hello = "Hello World!";
console.log(hello);

4、node hello.js打开或者引入xxx.html浏览器打开查看

在这里插入图片描述

typescript开发工具vscode自动编译.ts文件

1、创建 tsconfig.json 文件 cmd后执行命令 tsc --init 生成配置文件
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
然后就可以自动编译.ts文件

typescript中的数据类型

// typescript中为了使编写代码更加规范 有利于维护 增加了类型校验 

/*
  布尔类型 boolean
  数字类型 number
  字符串类型 string
  数组类型 array
  元祖类型 tuple
  枚举类型 enum
  任意类型 any
  null 和undefined
  void类型
  never类型
*/

//  布尔类型 boolean
var flag: boolean = true
flag = false

//  数字类型 number
var num: number = 123
console.log(num);

//  字符串类型 string
let str: string = 'fqniu'
console.log(str);

//  数组类型 array
// 第一种定义
let arr1: number[] = [1, 2, 3, 4]
console.log(arr1);
let arr2: string[] = ['1', '2', '3', '4']
console.log(arr2);
// 第二种定义
let arr3: Array<number> = [1, 2, 3, 4]
let arr4: Array<string> = ['1', '2', '3', '4']
// 第三种定义
let arr5: any[] = [1, 2, '3', 4, true]

//  元祖类型 tuple (定义数组的一种方式)
let arr7: [string, number, boolean] = ['fqniu', 25, true]

//  枚举类型 enum
enum Flag { success = 1, error = -1 }
let fs: Flag = Flag.success
let fe: Flag = Flag.error
console.log(fs, fe); // 1 -1

enum Color { red, blue, yellow }  // 如果这里默认不赋值的话打印的是索引值 0 1 2
let c: Color = Color.yellow
console.log(c); // 2 

enum Color1 { red, blue = 5, yellow }  // 如果这里默认不赋值的话打印的是索引值 0 1 2
let cr: Color1 = Color1.red
let cb: Color1 = Color1.blue
let cy: Color1 = Color1.yellow
console.log(cr); // 0
console.log(cb); // 5
console.log(cy); // 6 取上一个值, blue的值 +1


//  任意类型 any 
let numAny: any = 25
numAny = 'fqniu'
numAny = true
console.log(numAny);
// any的用处:获取dom元素节点 操作dom的样式等
// var oBox: any = document.getElementById('box')
// oBox.style.color = 'red'


//  null 和undefined
let undef: undefined
console.log(undef);

var nul: null
nul = null
console.log(nul);

// 一个元素可能是 number类型 可能是null 可能是undefined
var ele: number | null | undefined
console.log(ele);


//  void类型 typescript 中的void表示没有任何类型 一般用于定义方法的时候 方法没有返回值
function fun(): void {
  console.log('fun');
}
fun()
// 有返回值时
function fun1(): number {
  console.log('fun');
  return 123
}
fun1()

//  never类型:其他类型(包括null 和undefined)的子类型,代表从不会出现的值,这意味着声明never的变量只能被never类型所赋值
let error:never

// error = 25 // 报错

// 正确
error = (() => {
  throw new Error('错误')
})()


typescript中的函数

// 函数的定义
// js中函数声明定义
function fun1() { }
// js中匿名函数定义 函数表达式
var fun2 = function () { }


// ts中函数声明定义
function fun3(): string {
  return 'fqniu'
}
console.log(fun3()); // fqniu


// ts中匿名函数定义 函数表达式
var fun4 = function (): number {
  return 25
}
console.log(fun4()); // 25

// 1、函数的传参
function fun5(name: string, age: number): string {
  return `${name} -- ${age}`
}
console.log(fun5('fqniu', 25)); // fqniu -- 25

var fun6 = function (name: string, age: number): string {
  return `${name} -- ${age}`
}
console.log(fun6('nfq', 22)); // nfq -- 22

// 没有返回值的方法
function fun7(): void {
  console.log('fun7');
}
fun7()

// 2、函数的可选参数
// es5里面的方法的实参和形参可以不一样
// 但是ts必须一致,不一样的话可以配置可选参数,注意参数必须配置到参数的最后一个 加?

function fun8(name: string, age?: number): string {
  if (age) {
    return `${name} -- ${age}`
  } else {
    return `${name} -- 保密`
  }
}
console.log(fun8('fqniu')); // fqniu -- 保密
console.log(fun8('fqniu', 25)); // fqniu -- 25

// 3、默认参数
// es5里面没办法设置默认参数,es6和ts可以设置默认参数
function fun9(name: string, age = 20): string {
  if (age) {
    return `${name} -- ${age}`
  } else {
    return `${name} -- 保密`
  }
}
console.log(fun9('fqniu')); // fqniu -- 20
console.log(fun9('fqniu', 25)); // fqniu -- 25

// 4、剩余参数
function sum1(a: number, b: number, c: number, d: number): number {
  return a + b + c + d
}
console.log(sum1(1, 2, 3, 4)); // 10

function sum2(...result: number[]): number {
  var sum = 0
  for (var i = 0; i < result.length; i++) {
    sum += result[i]
  }
  return sum
}
console.log(sum2(1, 2, 3, 4, 5, 6)); // 21


// 5、函数的重载
// Java中方法的重载,是指的两个或者多个同名函数,但是他们的参数不一样,这时会出现函数重载的情况
// ts中的重载:通过为同一个函数提供多个函数类型定义来实现多种功能的目的
function getInfo(name: string): string;
function getInfo(age: number): string;
function getInfo(str: any): any {
  if (typeof str === 'string') {
    return '我叫 ' + str
  } else {
    return '我的年龄是' + str
  }
}
console.log(getInfo('fqniu'));
console.log(getInfo(22));

// 6、箭头函数
// this指向上下文
setTimeout(() => {
  console.log('fqniu ws');
}, 2000);


typescript中类的定义

// ts中类的定义
class Person {
  name: string; //属性 前面省略public关键词
  constructor(name: string) { // 构造函数 实例化类的时候触发的方法
    this.name = name;
  }
  fun(): void {
    console.log('fun', this.name);
  }
  getName(): string {
    return this.name
  }
  setName(name: string): void {
    this.name = name
  }
}

var p = new Person('fqniu')
console.log(p.name); // fqniu
console.log(p.getName()); //fqniu
p.setName('niuniu')
console.log(p.getName()); // niuniu

继承

javascript中的继承

  function Person() {
    this.name = 'fqniu' /*属性*/
    this.age = 25
    this.fun = function () {
      console.log(this.name + this.age);
    }
  }
  var p = new Person()
  console.log(p.name);
  p.fun()

  // 原型链上的属性会被多个实例共享,但是构造函数不会
  Person.prototype.sex = '男'
  Person.prototype.work = function () {
    console.log(this.name + '敲代码');
  }
  p.work()

  // 添加静态方法
  Person.getInfo = function () {
    console.log('我是静态方法');
  }
  Person.getInfo()

  // es中的继承 继承Person类 
  // 1、对象冒充实现继承
  function Web1() {
    Person.call(this) //对象冒充实现继承
  }
  var web1 = new Web1()
  web1.fun() // 对象冒充实现继承构造函数中的属性和方法
  // web.work() // 报错 index.html:48 Uncaught TypeError: web.work is not a function 但是没办法继承原型链上的属性和方法

  // 2、原型链实现继承
  function Web2() { }
  Web2.prototype = new Person() // 原型链实现继承
  var web2 = new Web2()
  console.log(web2.name); // fqniu
  web2.fun() // fqniu25
  web2.work() // fqniu敲代码
  // 原型链实现继承好处:既可以继承构造函数中的属性和方法,也可以继承原型链上的方法

  // 原型链实现继承的问题?  当实例化子类的时候,没办法给父类传参
  function Person1(name, age) {
    this.name = name /*属性*/
    this.age = age
    this.fun = function () {
      console.log(this.name + this.age);
    }
  }
  function Web3(name, age) { }
  Web3.prototype = new Person1() // 原型链实现继承
  var web3 = new Web3('nfq', 25)
  console.log(web3.name); // undefined  因为实例化子类的时候,没办法给父类传参


  // 组合继承模式
  function Person2(name, age) {
    this.name = name /*属性*/
    this.age = age
    this.fun = function () {
      console.log(this.name + this.age);
    }
  }
  Person2.prototype.sex = '男'
  Person2.prototype.work = function () {
    console.log(this.name + '敲代码');
  }
  function Web4(name, age) {
    Person2.call(this, name, age) // 对象冒充继承,实例化子类可以给父类传参
  }
  Web4.prototype = new Person2() // 原型链实现继承
  // 或者  
  // Web4.prototype = Person2.prototype
  var web4 = new Web4('nfq', 25)
  console.log(web4.name);  // nfq
  web4.fun() // nfq25
  web4.work() // nfq敲代码

typescript中的继承

// ts中实现继承 extends、 super
class Person {
  name: string; //属性 前面省略public关键词
  constructor(name: string) { // 构造函数 实例化类的时候触发的方法
    this.name = name;
  }
  fun(): void {
    console.log('fun', this.name);
  }
  getName(): string {
    return this.name
  }
  setName(name: string): void {
    this.name = name
  }
}

class Web extends Person {

  constructor(name: string) {
    super(name) // 初始化父类的构造函数
  }
  work(): void {
    console.log(`${this.name}在敲代码`);
  }
  // fun(): void {
  //   console.log('fun - 子类', this.name);
  // }
}

var w = new Web('fqniu')
w.fun() // fun fqniu
w.work() // fqniu在敲代码


// 类里面的修饰符 typescript里面定义属性的时候提供了三种修饰符
/*
  public:公有 —— 在当前类里面、子类、类外面都可以访问
  protected:保护类型 —— 在当前类里面,子类都可以访问,在类外部无法访问
  provite:私有 —— 只有当前类里面访问,子类、类外部都无法访问

  属性不加修饰符 默认是public公有

*/

class Person1 {
  protected name: string; // 保护类型
  constructor(name: string) { // 构造函数 实例化类的时候触发的方法
    this.name = name;
  }
  fun(): void {
    console.log('fun', this.name);
  }
  getName(): string {
    return this.name
  }
  setName(name: string): void {
    this.name = name
  }
}

class Web1 extends Person1 {
  constructor(name: string) {
    super(name) // 初始化父类的构造函数
  }
  work(): void {
    console.log(`${this.name}在敲代码`);
  }
  // fun(): void {
  //   console.log('fun - 子类', this.name);
  // }
}

var w1 = new Web1('fqniu')
w1.fun() // fun fqniu
w1.work() // fqniu在敲代码

typescript类的静态属性和静态方法

// 类的静态属性,静态方法
class Person2 {
  public name: string;
  static sex: string = '男'; // 静态属性
  constructor(name: string) { // 构造函数 实例化类的时候触发的方法
    this.name = name;
  }
  fun(): void {
    console.log('fun', this.name);
  }
  // 静态方法
  static getInfo() {
    // console.log('name', this.name); // 类里面没法直接调用类的属性 Person2
    console.log('sex', this.sex);
  }
}

var p2 = new Person2('fqniu')
console.log(p2.name); // fqniu

Person2.getInfo() // 调用静态方法
console.log(111, Person2.sex); // 调用静态属性 男

typescript类的多态

// 多态 父类定义一个方法不去实现,让继承他的子类去实现,每个子类有不同的表现 属于继承
class Person1 {
  public name: string; 
  constructor(name: string) { 
    this.name = name;
  }
  fun(): void {
    console.log('fun', this.name);
  }
}

class Web1 extends Person1 {
  constructor(name: string) {
    super(name) 
  }
  fun(): void {
    console.log('fun', this.name + '敲代码呢');
  }
}

class Web2 extends Person1 {
  constructor(name: string) {
    super(name) 
  }
  fun(): void {
    console.log('fun', this.name + '睡觉呢');
  }
}

typescript的抽象类

// typescript中的抽象类 它是提供其他类型继承的基类,不能直接实例化
// 用abstract 关键字定义抽象类和抽象方法,抽象类中的方法不包含具体实现并且必须在派生系中实现
// abstract抽象方法只能放在抽象类里面
// 抽象类和抽象方法用来定义标准,标准这个类要求它的子类必须包含某个方法

abstract class Person1 {
  public name: string;
  constructor(name: string) {
    this.name = name;
  }
  abstract fun(): void;
}
// 注意不能直接实例化 Person1

class Web1 extends Person1 {
  constructor(name: string) {
    super(name)
  }
  // 抽象类的子类必须实现抽象类里面的抽象方法 fun
  fun(): void {
    console.log('fun', this.name + '敲代码呢');
  }
}
var w1 = new Web1('fqniu')
console.log(w1.name);
w1.fun() // fun fqniu敲代码呢

typescript中的接口

/*
  接口的作用:在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范,在程序设计里面,接口起到了一种限制和规范的作用。
  接口定义了某一批所需要规范,接口不关心这些类的内部状态数据,也不关心这些类里面方法的实现细节,他只规定这批类里面必须提供某些方法
  提供这些方法的类就可以满足实际需求,typescript中的接口类似于Java,同时还增加了更灵活的接口类型,包括属性,函数,可索引的类等

  typescript中的接口
    1、属性类接口
    2、函数类型的接口
    3、可索引的接口
    4、类类型的接口
    5、接口扩展
*/

// 1、属性类的接口 对json的约束
// function label(): void {
//   console.log('faniu');
// }
// label()

// ts 定义方法传入参数
// function label(label: string): void {
//   console.log('faniu');
// }
// label('nnn')

// 接口:行为和动作的规范,对批量方法进行约束
interface FullName {
  firstName: string;   // 一定要加;结尾
  secondName: string;
}

function label(name: FullName): void {
  // 必须传入对象 firstName, secondName
  console.log(name.firstName + name.secondName);
}

// 这种写法,里面只能有firstName和secondName字段,不然报错
// label({
//   firstName: 'fq',
//   secondName: 'niu'
// })

// 这种定义到外部的写法,只要包含必要的字段 firstName 和 secondName字段,就不会报错
let obj = {
  firstName: 'fq',
  secondName: 'niu',
  sex: '男'
}
label(obj)


// 接口:可选属性 属性后面加? 
interface Info {
  firstName: string;
  secondName?: string;
  age?: number
}
function getName(name: Info) {
  console.log(name);

}
let obj1 = {
  firstName: 'fq',
  // secondName: 'niu', // 可选属性
  // age: 25 // 可选属性
}
getName(obj1)



// 案例 封装ajax函数
interface Config {
  type: string;
  url: string;
  data?: string;
  dataType: string;
}

function ajax(config: Config) {
  let xhr = new XMLHttpRequest()
  xhr.open(config.type, config.url, true);
  xhr.send(config.data)
  xhr.onreadystatechange = function () {
    if (xhr.readyState == 4 && xhr.status == 200) {
      console.log('成功');
      if (config.dataType == 'json') {
        JSON.parse(xhr.responseText)
        console.log(JSON.parse(xhr.responseText));
      } else {
        console.log(xhr.responseText);
      }
    }
  }
}

ajax({
  type: 'get',
  url: 'https://www.fqniu.xyz:5002/api/goodlist',
  dataType: 'json'
})



// 2、函数类型接口: 对方法传入的参数,以及返回值进行约束
// 加密函数类型接口
interface encrypt {
  (key: string, value: string): string;
}

let md5: encrypt = function (key: string, value: string): string {
  // 模拟操作
  return key + value;
}
md5('fqniu', 'value')
console.log(md5('fqniu', 'value')); // fqniuvalue


// 3、可索引的接口:数组、对象的约束
interface UserArr {
  [index: number]: string;
}
var arr: UserArr = ['1', '2', '3']
console.log(arr);

interface Userobj {
  [index: string]: string;
}
var user: Userobj = { name: 'fqniu' };


// 4、类类型的接口: 对类的约束 和抽象类 有点相似  implements类实现公共接口的关键字
interface Person {
  name: string;
  fun(str: string): void;
}

class Web implements Person {
  name: string;
  constructor(name: string) {
    this.name = name
  }
  fun() {
    console.log(this.name + '敲代码呢');
  }
}

let w = new Web('niuniu')
w.fun()


// 5、接口扩展: 接口可以继承接口
interface Animal {
  fun(): void;
}
interface Pserson extends Animal {
  work(): void;
}

class Mine implements Person {
  name: string;
  constructor(name: string) {
    this.name = name
  }
  fun() {
    console.log(this.name + '睡觉呢');
  }
  work() {
    console.log(this.name + '敲代码');
  }
}

let m = new Mine('nfq')
m.work() // nfq敲代码


typescript中的泛型

/*
  泛型:软件工程中,不仅要创建一致的定义良好的API,同时要考虑可重用性,组价不仅能够支持当前的数据类型
  同时也能支持未来的数据类型,这在创建大型系统时为提供了十分灵活的功能

  泛型就是解决类,接口,方法的复用性,避免重复的代码,以及对不待定数据类型的支持(类型校验)
*/


// 1、泛型定义
// 泛型 可以支持不特定的数据类型,要求传入的参数和返回的参数一致


// 2、泛型函数
// T表示泛型,具体什么类型是调这个方法的时候决定的
function getData<T>(value: T): T {
  return value;
}
getData<number>(25)
getData<string>('fqniu')


// 3、泛型类
// 例如有个最小堆算法,需要同时支持返回数字和字符串两种类型,通过类的泛型来实现
class MinClass<T>{
  public list: T[] = []
  add(value: T): void {
    this.list.push(value)
  }
  min(): T {
    var minNum = this.list[0]
    for (var i = 0; i < this.list.length; i++) {
      if (minNum > this.list[i]) {
        minNum = this.list[i]
      }
    }
    return minNum
  }
}
var min = new MinClass<number>() // 实例化类 并且制定了T代表的类型是 number
min.add(11)
min.add(111)
min.add(1111)
min.add(10)
console.log(min.min()); // 10

var min1 = new MinClass<string>() // 实例化类 并且制定了T代表的类型是 string
min1.add('f')
min1.add('n')
min1.add('b')
min1.add('q')
console.log(min1.min()); // b




// 4、泛型接口
// 第一种写法
interface configFn1 {
  <T>(value: T): T;
}
var getDataFun1: configFn1 = function <T>(value: T): T {
  console.log(value);
  return value
}
getDataFun1<string>('fqniu')


// 第二种写法
interface configFn2<T> {
  (value: T): T;
}
function getDataFun2<T>(value: T): T {
  console.log(value);
  return value
}
var myGetData: configFn2<string> = getDataFun2
getDataFun2('niuniu')


以上内容根据视频Typescript教程——大地老师讲解手敲整理

后续更新中…


点击全文阅读


本文链接:http://m.zhangshiyu.com/post/40360.html

函数  类型  方法  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1