TypeScript学习手记

1.TypeScript官网、安装与运行

名称备注
官方地址https://www.typescriptlang.org
安装typescriptnpm install typescript-g 为全局安装
初始化typescripttsc --init初始化
初始化typescripttsc 文件名(包含扩展名)初始化
运行编译器npx tsc生成js文件
安装ts-nodenpm install ts-node
运行typescriptts-node 文件名(包含扩展名)输出ts文件结果
安装superagentnpm install superagent --save爬取数据使用
安装superagent翻译文件npm install @types/superagent -Dsuperagent.t.ts翻译文件
安装cheerionpm install cheerio --savecheerio库 获取页面区块的内容
安装cheerio翻译文件npm install @types/cheerio -Dcheerio 库 获取页面区块的内容
安装nodemonnpm install nodemon -D安装nodemon,自动监听源文件并编译js文件
安装concurrentlynpm install concurrently -D安装concurrently ,并行执行
安装npm包npm init -y
安装expressnpm install express --save

2.TypeScript基础类型与对象类型

名称示例
基础类型null, undefined, symbol, boolean, void, number, string, neverconst count: number = 123
对象类型{}const count: {name: string} = {name: ‘hyb’}
数组类型[]const count: number[] = [1, 2, 3]
类类型Classconst count: 类 = new 类()
函数类型functionconst count: () => number = () => {return 123}
declare关键字定义全局变量 declaredeclare var $: (param: () => void) => void
declare关键字定义全局函数 declaredeclare function $(param: () => void) => void
declare关键字定义全局函数 declare .d.ts中,函数可以重载declare function $(param: string): {html: (html: string) => {}}
// 函数相关类型示例
// never代表该函数永远也执行不到最后。
function add(first: number, second: number): never{
  let j=0
  for(let i=1;i>j;i++){
    // ......  
  }
  return first + second;
}
// 如系统可以自动推断出类型。可以不加返回值类型,如果系统不能推断出类型,则建议添加返回值类型。
function add(first: number, second: number): number {
  return first + second;
}
// 函数对象参数类型注解示例
function add(
  {first, second}:{first: number, second: number}
): number {
  return first + second;
}
// 变量/常量函数类型示例
const func = (str: string) => { return parseInt(str, 10) } // 简洁写法,可自动推断类型
const func1: (str: string) => number = (str) => { return parseInt(str, 10) }
// 时间类型示例
const date = new Date() // 系统可以自动推断出类型
const date: Date = new Date() // 注解类型
// 多个类型示例
let temp: number | string = 123
temp = '456'
// 对象类型示例
interface Person { name: 'string'}
const rawData = '{"name": "hyb"}'
const newData = Person = JSON.parse(rawData)

3.数组、元组及类型别名

// 当数组内即需要数字类型,又需要字符串类型时,可以是如下写法
const arr: (number | string)[] = [1, 2, 3]
// 元组,当要求第一项必须是字符串,第二项必须是数字,则可以是如下写法
const teacher: [string, number] = ['hyb', 18]
// 类型别名示例
type User = {name: string, age: number}
// 或可以这样写
class User {
  name: string;
  age: number;
}
const objectArr: User[] = [{
  name: 'hyb',
  age: 28
}]

4.Interface接口

interface Person {
  readonly name: string; // readonly 代表只读属性,该属性只能读取,不能修改。
  age?: number; // ? 代表该属性是可选的,可填可不填。
  [propName: string]: any; // [propName: string]: any 代表可以新增任意属性,只要名是string类型,属性值是任意类型即可。
  say(): string; // 代表该接口中需要有say方法,该方法返回值类型是string类型
}
interface Teacher extends Person { // extends 是继承属性,代表Teacher继承了Person的属性和方法
  teach(): string
}
interface SayHi { // 接口可以定义函数类型
  (teach: string): string // 代表当前接口定义的函数需要传入string类型的teach并且返回string类型的值
}
class User implements Person { 
  // implements 代表类中引入接口的规范
}

5.类的定义与继承

class Person { // 类的定义
  name = 'hyb' // 类中可以定义属性
  getName() { // 类中可以定义方法
	return this.name
  }
}
class Teacher extends Person { // 类可以继承类,被继承的为父类(Person),继承的为字类(Teacher)
  getTeacherName() { // 类中可以定义方法
	return this.name
  }
  getName() { // 子类可以重写父类中的方法
	// return 'bin'
	return super.getName() + 'bin' // 字类中调用父类的方法可以使用super
  }
}
class Person { // 类中的访问类型
  public name = 'hyb' // public 如不写访问类型,则默认是public。代表允许在类外被调用,
  private age = 18 // private 只允许在类内被使用
  protected  getName() { // protected  允许在类内及继承的子类中使用
	return this.name
  }
}
class Person { // 类中的构造器
  // 传统写法
  public name: string
  constructor(name: string){ // constructor 构造器方法
    this.name = name
  }
  // 简化写法
  constructor(public name: string){} // constructor 构造器方法
}
class Teacher extends Person{
  constructor(public age: number){ // constructor 构造器方法
    // 子类继承父类时,如果子类有构造器,则子类需要调用父类的super(),如父类有参数,则需要传入相应参数。如没有,则传空
    super('hyb') 
  }
}

6.静态属性,Setter和Getter

class Person{ // 通过get和set对私有属性进行取值和赋值
  constructor(private _name: string){} // 私有变量建议在属性名前加_来表示
  get name() { return this._name } // 取值的get方法
  set name(name: string) { this._name = name } // 赋值的set方法
}
// const person = new Person('hyb')
// person.name // 取值
// person.name = 'hyb' // 赋值 

// 单例模式
class Demo {
  private static instance: Demo
  private constructor(public name: string) {}
  static getInstance() { // static 静态属性
    if(!this.instance){
	  this.instance = new Demo('hyb')
	}
	return this.instance
  }
}
const demo1 = Demo.getInstance()

7.抽象类

class Person {
  public readonly name: string; // readonly 修饰符 只能读取,不能修改readonly 修饰的属性
  constructor(name: string) {
    this.name = name;
  }
}
const person = new Person('hyb');
// person.name = 'bin' // 会报错

// 抽象类是用来捕捉子类的通用特性的,而接口则是抽象方法的集合;
// 抽象类不能被实例化,只能被用作子类的超类,是被用来创建继承层级里子类的模板
// 而接口只是一种形式,接口自身不能做任何事情。
// 其次,抽象类可以有默认的方法实现,子类使用extends关键字来继承抽象类
// 如果子类不是抽象类的话,它需要提供抽象类中所有声明方法的实现。
// 而接口完全是抽象的,它不存在方法的实现,子类使用关键字implements来实现接口,它需要提供接口中所有声明方法的实现。
// 抽象类可以有构造器,除了不能实例化抽象类之外,它和普通类没有任何区别
// 抽象方法可以有public、protected和default这些修饰符。
// 而接口不能有构造器,是完全不同的类型,接口方法默认修饰符是public,不可以使用其它修饰符。				
abstract class Geom { // abstract 抽象类修饰符
  width: number;
  getType() {
	return 'Gemo';
  }
  abstract getArea(): number;
}
class Circle extends Geom {
  getArea() {
	retuen 123;
  }
}

8.联合类型和类型保护(类型断言)

interface Bird {
  fly: boolean
  sing: () => {}
}
interface Dog {
  fly: boolean
  bark: () => {}
}
// as 语法类型保护
function trainAnial(animal:Bird | Dog) {
  if(animal.fly){
	(animal as Bird).sing()
  } else {
	(animal as Dog).bark()
  }
}
// in 语法类型保护
function trainAnial(animal:Bird | Dog) {
  if('sing' in animal){
	animal.sing()
  } else {
	animal.bark()
  }
}
// typeof 语法类型保护
function add(first: string | number, second: string | number) {
  if(typeof first === 'string' || typeof srecond === 'string') {
	return `${first}${second}`
  }
  return first + second
}
// 使用 instanceof语法来做类型保护
class NumberObj {
  count: number;
}
function add(first: object | NumberObj , second: object | NumberObj ) {
  if(first instanceof NumberObj && srecond instanceof NumberObj) {
	return first.count + srecond.count
  }
  return 0
}

9.Enum枚举类型

// 如下输出结果分别为:0,4,5
enum Status {
  OFFLINE,
  ONLINE = 4,
  DELETED
}
// 如下输出结果分别为:0,1,2
enum Status {
  OFFLINE,
  ONLINE,
  DELETED
}
// 如下输出结果分别为:1,2,3
enum Status {
  OFFLINE = 1,
  ONLINE,
  DELETED
}
Status.OFFLINE ===> 0
Status[0] ===> OFFLINE

10.泛型

// 函数泛型1
function jojn<T, P>(first: T, second: P){
  return `${first}${second}`
}
jojn<string, string>('1', '1')
// 函数泛型2
function map<T>(params: T[]){ // Array<T>等价T[]
  return params
}
function map<T>(params: Array<T>){ // Array<T>等价T[]
  return params
}
map<string>(['123'])
// 类泛型
interface Item {
  name: string;
}
class DataManager<T extends Item> { // 泛型可以继承,也可以继承类型。例如:<T extends number | string>
  constructor(private data: T[]) {}
  getItem(index: number): string {
	return this.data[index].name
  }
}
const data = new DataManager([{
  name: 'hyb'
}])
// 使用泛型做为一个具体的类型注解
function hrllo<T>(params: T) {
  return params;
}
const func: <T>(param: T) => T = hello
// 泛型中keyof语法的使用,可以使泛型为动态的类型,根据实际情况来变化泛型的类型
interface Person {
  name: string
  age: number
  gender: string
}
class Teacher {
  constructor(private info: Person) {}
  getInfo<T extends keyof Person>(key: T): Person[T] {

	  return this.info[key]

  }
}
const teacher = new Teacher({
  name: 'hyb',
  age: 18,
  gender: 'male'
})
teacher.getInfo('name')

11.命名空间-namespace

// 使用namespace命名空间将多个类包裹起来后,只暴露需要暴露的类
///<reference path='./componwnts.ts' /> // 如跨文件调用时,可用此方法进行注解。
namespace Home {
  class Header {...}
  class Footer {...}
  export class Page {...}
}
new Home.Page()
// 命名空间可以包含子命名空间
namespace Home {
  export namespace SubHome { // 命名空间可以用export 暴露导出
    export interface User { // 命名空间可以暴露导出接口
      name: string
	}
  }
}

12.全局类型与函数重载以及模块化

// 定义全局变量 .d.ts
declare var $: (param: () => void) => void
// 定义全局函数
interface JqueryInstance {
  html: (html: string) => JqueryInstance 
}
// 函数重载
declare function $(readyFunc: ()=> void): void
declare function $(selector: string): JqueryInstance 
// 对类、对象进行类型定义以及命名空间的嵌套(适合即是函数又是对象时的写法)
declare namespace $ {
  namespace fn {
	class init {}
  }
}
// 使用interface 语法实现函数重载(适合只是函数重载的写法)
interface JQuery {
  (readyFunc: () => void): void;
  (selector: string): JqueryInstance 
}
declare var $: JQuery;
// ES6模块化
declare module 'jquery' {
  interface JqueryInstance {
    html: (html: string) => JqueryInstance 
  }
  function $(readyFunc: ()=> void): void
  function $(selector: string): JqueryInstance 
  namespace $ {
    namespace fn {
	  class init {}
    }
  }
  export = $
}
//---------------------
import $ from 'jquery'
$(function(){
  ......
})

13.类的装饰器

// 装饰器本身是一个函数,装饰器通过 @ 符号来使用,装饰器接收的参数是构造函数。
// 装饰器使用需要在tsconfig.json文件中将Experimental Options的代码注释释放掉。@testDecorator()
// 装饰器可以有多个,多个装饰器的执行顺序是从下到上,从左到右,即靠近类的装饰器先执行。
// 如果外层包裹了函数,则装饰器需要在后面加上括号。
function testDecorator() {
  return function<T extends new (...args: any[]) => any>(constructor: T) {
    name = 'bin'
    getName() {
	  return this.name
	}    
  }
}
const Test = testDecorator()(
  class {
	name: string
	constructor(name: string) {
	  this.name = name
	}
  }
)
const test = new Test('hyb')
console.log(test.getName())

14.方法装饰器

// 普通方法,target 对应的是类的prototype
// 静态方法,target 对应的是类的构造函数
// 
function getNameDecorator(target: any, key: string, descriptor: PropertyDescriptor) {
  console.log(target, key)
  descriptor.writable = false // 不允许对方法内的函数进行修改
  descriptor.value = function(){ // 对原始方法进行变更
	return 'decorator'
  }
}
class Test {
  name: string
  constructor(name: string) {
	this.name = name
  }
  @getNameDecorator
  getName() {
	return '123'
  }
}

15.访问器的装饰器

function visitDecorator(target: any, key: string, descriptor: PropertyDescriptor) {
  descriptor.writable = false // 不允许对方法内的函数进行修改
}
class Test {
  private _name: string
  constructor(name: string) {
	this._name = name
  }
  get name() {
	return this.name
  }
  @visitDecorator
  set name(name: string) {
	this._name = name
  }
  const = test = new Test('hyb')
  test.name = 'hybin'
  console.log(test.name)

16.属性的装饰器

function nameDecorator(target: any, key: string):any {
  const descriptor: PropertyDescriptor = {
	writable = false // 不允许对方法内的函数进行修改
  }
  return descriptor;
}
const = test = new Test('hyb')
test.name = 'hybin'
function nameDecorator(target: any, key: string):any {
  target[key] = 'lee' // 修改的并不是实例上的name,而是原型上的name
}
// name 放在实例上
class Test {
  @nameDecorator
  name = 'hyb'
}
const test = new Test()
console.log((test as any).__proto__.name)

17.参数装饰器

// 第一个参数是原型,第二个参数是方法名,第三个是参数所在位置
function paramDecorator (target: any, key: string, paramIndex: number):any {
  console.log(target, key, paramIndex)
}
class Test {
  getInfo(@paramDecorator name: string, age: number) {
	console.log(name, age)
  }
}
const test = new Test()
test.getInfo('hyb', 30)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值