TypeScript 从零实现 axios 0x1

基础类型

let isDone: boolean = true // 布尔值

let decLiteral: number = 20 // 数字
let hexLiteral: number = 0x14
let binaryLiteral: number = 0b10100
let octalLiteral: number = 0o24 //8进制

let name: string = 'Jack' //字符串
let sentence: string = `Hello ${name}`

let list: number[] = [1, 2, 3] // 数组
let list2: Array<number> = [4, 5, 6]

let x: [string, number] // 元组 Tuple
x = ['hello', 2]
x[2] = 3 // 越界元素为联合类型,既可以是string也可以是number 最新版越界会报错

// 枚举
enum Color {
    Red = 1,
    Green,
    Blue
}
let c: Color = Color.Green
let colorName: string = Color[2] //Green

// any 不做检查,回归JS
let notSure: any
notSure = 'not'
notSure = 3
let list: any[] = [1, true, 'free']

//void 没有任何类型,如函数中不返回任何值
function log(content): void {
    console.log(content)
}

// null

// undefined

// never 不存在的类型,是任何类型的子类型
// 场景一
function error(message: string): never {
    throw new Error(message)
}
function fail() {
    return error('something failed')
}
// 场景二
function inifiniteLoop(): never {
    while(true) {}
}

// Object
declare function create(o: object | null): void
create(o: {prop: 0})
create(o: null)

create(o: 1)
create(o: 'string')

//类型断言
let someValue: any = 'this is a string'
let strLength: number = (<string>SomeValue).length
let strLength2: number = (SomeValue as string).length // 强制转化为一种类型

变量声明

var

闭包

function f() {
  var a = 10
  return function g() {
    var b = a + 1
    return b
  }
}

var g = f()
var result = g() 
console.log(result)// 11

 

let

块级作用域

function f(input: boolean) {
    let a = 100
    if (input) {
        let b = a + 1
        return b
    }
    return b // error
}
  • 暂时性死区 声明前不能读写(var 不存在这种现象)
  • 不能被重定义(var可以)

 const

除非计划要修改,否则一律使用const

const numLiveForCat = 9

const kitty = {
    name: 'kitty',
    numLives: numLiveForCat
}

kitty.name = 'Jerry'
kitty.numLives--

解构

// 数组解构
let input = [1, 2]
let [first, second] = input
// 等价于
let first = input[0]
let second = input[1]

// 剩余变量
let [first, ...rest] = [1,2,3,4] // rest [2,3,4]
let [,second,,fourth] = [1,2,3,4] // second 2 fourth 4

// 对象解构
let obj = {
    a: 'foo',
    b: 12,
    c: 'bar'
}

let {a, b} = obj // a 'foo' b 12

// 默认值
function keepWholeObject(wholeObject: { a: string, b?: number }) {
    let { a, b = 1001 } = wholeObject
}

// 函数声明
function f({a = '', b = 0} = {}): void {}
function f({a, b = 0} = {a: ''}): void {}

 展开(扩展)

// 数组展开
let first = [1, 2]
let second = [3, 4]
let bothPlus = [0, ...first, ...second, 5] // [1,2,3,4,5]
 
// 对象展开
let defaults = {
    food: 'spicy',
    price: '$10',
    ambiance: 'noisy'
}
let search = {...defaults, food: 'rich'} // {food: 'rich', price: '$10', ambiance: 'noisy'}
let search2 = {food: 'rich', ...defaults} // {food: 'spicy', price: '$10', ambiance: 'noisy'}

接口

基本用法

interface LabelledValue {
    label: string
}
function printLabel(labelledObj: LabelledValue) {
    console.log(labelledObj.label)
}
let myObj = { size: 10, label: 'Size 10 Object'}
printLabel(myObj) // Size 10 Object

可选属性

// 对可能出现的属性做一个预定义
// 错误提示
interface Square {
    color: string
    area: number
}
interface SquareConfig {
    color?: string
    width?: number
}
function createSquare(config: SquareConfig): Square {
    let newSquare = {
        color: 'white',
        area: 100
    }
    if (config.color) {
       newSquare.color = config.color 
    }
    if (config.width) {
        newSquare.area = config.width * config.width
    }
    return newSquare
}
let mySquare = createSquare(config: {color: 'black'})

只读属性

interface Point {
    readonly x: number
    readonly y: number
}
let p1: Point = {x: 10, y: 20}
Point.x = 5 // error

// 泛型只读数组
let arr: number[] = [1,2,3,4]
let ro: ReadonlyArray<number> = arr
ro[0] = 12 // error

 额外属性检查

interface Square {
    color: string
    area: number
}
interface SquareConfig {
    color?: string
    width?: number
    [propName: string]: any // 额外类型
}
function createSquare(config: SquareConfig): Square {
    let newSquare = {
        color: 'white',
        area: 100
    }
    if (config.color) {
       newSquare.color = config.color 
    }
    if (config.width) {
        newSquare.area = config.width * config.width
    }
    return newSquare
}
let mySquare = createSquare(config: {color: 'black'})

函数类型

interface SearchFunc {
    (source: string, subString: string): boolean
}
let mySearch: SearchFunc
mySearch = function(src: string, sub: string): boolean {
    let result = src.search(sub)
    return result > -1
}

 可索引的类型

interface StringArray {
    [index: number]: string
}
let myArray: StringArray
myArray = ['Bob', 'Fred']
let myStr: string = myArray[0]

类类型

// 接口只描述类的公共部分,不检查私有部分
interface ClockInterface {
    currentTime: Date
    setTime(d: Date)
}
class Clock implements ClockInterface {
    currentTime: Date
    constructor(h: number, m: number) {}
    setTime(d: Date) {
        this.currentTime = d
    }
}

 接口继承类

接口继承接口

interface Shape {
    color: string
}
interface Square extends Shape {
    sideLength: number
}
let square = {} as Square
square.color = 'blue'
square.sideLength = 10

继承多个接口

interface Shape {
    color: string
}
interface PenStroke {
    penWidth: number
}
interface Square extends Shape, PenStroke {
    sideLength: number
}
let square = {} as Square
square.color = 'blue'
square.sideLength = 10
square.penWidth = 20

 混合类型

interface Counter {
    (start: number): string
    interval: number
    reset(): void
}
function getCounter(): Counter {
    let counter = (function(star: number){
        
    }) as Counter
    counter.interval = 123
    counter.reset = function() {}
    return counter
}
let c = getCounter()
c(10)

接口继承类

class Control {
    private state: any
}
interface SelectableControl extends Control {
    select()
}
class Button extends Control implements SelectableControl {
    select() {}
}

基本使用

class Greeter {
  greeting: string
  constructor(message: string) {
    this.greeting = message
  }
  greet() {
    return `Hello ${this.greeting}`
  }
}
let greeter = new Greeter('TS')
greeter.greet()

 继承后扩展类的方法

// 基类(超类)
class Animal {
  move(distance: number = 0) {
    console.log(`Animal move ${distance}`)
  }
}
// 子类
class Dog extends Animal {
  bark() {
    console.log('Woof! Woof!')
  }
}

const dog = new Dog()
dog.bark()
dog.move(1)

继承并定制父类的方法

// 基类(超类)
class Animal {
  name: string
  constructor(name: string) {
    this.name = name
  }
  move(distance: number = 0) {
    console.log(`${this.name} moved ${distance}m`)
  }
}
// 子类
class Snake extends Animal {
  constructor(name: string) {
    super(name)
  }
  move(distance: number = 5) {
    console.log('Slithering...')
    super.move(distance)
  }
}
class Hourse extends Animal {
  constructor(name: string) {
    super(name)
  }
  move(distance: number = 50) {
    console.log('Galloping...')
    super.move(distance)
  }
}

const sam = new Snake('Sammy')
const tom: Animal = new Hourse('Tommy')

sam.move()
tom.move(24)

 公共、私有、修饰符

private

class Animal {
  private name: string
  constructor(name: string) {
    this.name = name
  }
  move(distance: number = 0) {
    console.log(`${this.name} moved ${distance}m`)
  }
}

class Rhino extends Animal {
  constructor() {
    super('Rhino')
  }
}

class Employee {
  private name: string
  constructor(name: string) {
    this.name = name
  }
}

let animal = new Animal('Goat')
let rhino = new Rhino()
let employee = new Employee('Bob')

animal = rhino
// animal = employee //error

protected 修饰符

class Person {
  protected name: string
  constructor (name: string) {
    this.name = name
  }
}
class Employee extends Person {
  private department: string
  constructor(name: string, department: string) {
    super(name)
    this.department = department
  }
  getElevatorPitch() {
    return `Hello, my name is ${this.name} and I work in ${this.department}`
  }
}

let howard = new Employee('Hpward', 'Sales')
console.log(howard.getElevatorPitch())
// console.log(howard.name) // error

 constructor 加protected后只能new他的派生类,即在派生类中才能访问constructor

class Person {
  protected name: string
  protected constructor (name: string) {
    this.name = name
  }
}
class Employee extends Person {
  private department: string
  constructor(name: string, department: string) {
    super(name)
    this.department = department
  }
  getElevatorPitch() {
    return `Hello, my name is ${this.name} and I work in ${this.department}`
  }
}

let howard = new Employee('Hpward', 'Sales')
console.log(howard.getElevatorPitch())
// console.log(howard.name) // error

let john = new Person('John')

readonly 修饰符

class Person {
  readonly name: string
  constructor (name: string) {
    this.name = name
  }
}
let john = new Person('John')
// john.name = 'john' // error

参数属性

即给构造函数参数前面加上访问限定符

class Person {
  constructor (readonly name: string) {
    this.name = name
  }
}
let john = new Person('John')
console.log(john.name)

 存取器

let psw: string = 'admin'
class Employee {
  private _fullName: string
  get fullName(): string {
    return this._fullName
  }
  set fullName(newName: string) {
    if (psw && psw === 'admin') {
      this._fullName = newName
    } else {
      console.log('Error')
    }
  }
}
let employee = new Employee()
employee.fullName = 'Bob Smith'
if(employee.fullName) {
  console.log(employee.fullName)
}

编译结果

var psw = 'admin';
var Employee = /** @class */ (function () {
    function Employee() {
    }
    Object.defineProperty(Employee.prototype, "fullName", {
        get: function () {
            return this._fullName;
        },
        set: function (newName) {
            if (psw && psw === 'admin') {
                this._fullName = newName;
            }
            else {
                console.log('Error');
            }
        },
        enumerable: true,
        configurable: true
    });
    return Employee;
}());
var employee = new Employee();
employee.fullName = 'Bob Smith';
if (employee.fullName) {
    console.log(employee.fullName);
}

 静态属性

class Grid {
  static origin = {
    x: 0,
    y: 0
  }
  scale: number
  constructor(scale: number) {
    this.scale = scale
  }
  calculateDistanceFromOrigin(point: {x: number, y: number}) {
    let dx = point.x - Grid.origin.x
    let dy = point.y - Grid.origin.y
    return Math.sqrt(dx * dx + dy * dy) * this.scale
  }
}

const g1 = new Grid(1.0)
const g2 = new Grid(5.0)

console.log(g1.calculateDistanceFromOrigin({x:3,y:4}))
console.log(g2.calculateDistanceFromOrigin({x:3,y:4}))

抽象类

abstract class Deparment {
  name: string
  constructor(name: string) {
    this.name = name
  }
  printName(): void {
    console.log(`Department name is ${this.name}`)
  }
  abstract printMetting(): void
}
class AccoutingDepartment extends Deparment {
  constructor() {
    super('Accounting ad Auditing')
  }
  printMetting(): void {
    console.log('accounting meeting')
  }
  generateReports(): void {
    console.log('Accounting reports')
  }
}
let deparment : AccoutingDepartment
deparment = new AccoutingDepartment()
deparment.printName()
deparment.printMetting()
deparment.generateReports()

 补充

修改静态属性

class Greeter {
  static standardGreeting = 'Hello ,there '
  greeting: string
  constructor(message?: string) {
    this.greeting = message
  }
  greet() {
    if (this.greeting) {
      return `Hello, ${this.greeting}`
    } else {
      return Greeter.standardGreeting
    }
  }
}

let greeter: Greeter
greeter = new Greeter('world')
console.log(greeter.greet())

let greeter2: Greeter
greeter2 = new Greeter()
console.log(greeter2.greet())

// 修改静态属性
let greeterMaker: typeof Greeter = Greeter
greeterMaker.standardGreeting = 'Hey there'
let greeter3: Greeter = new greeterMaker()
console.log(greeter3.greet())

 

函数

基础

// 命名函数
function add(x, y) {
    return x + y
}

// 匿名函数
let myAdd = function (x, y) {
    return x + y
}

let z = 100
// 使用全局变量
function addToZ(x, y) {
    return x + y + z
}

// 函数类型
let myAdd2: (x: number, y: number) => number = function(x: number, y: number): number {
    return x + y
}

可选参数

function buildName(firstName: string, lastName?: string) {
  if (lastName) {
    return `${firstName} ${lastName}`
  } else {
    return firstName
  }
}
let result1 = buildName('Bob')
let result2 = buildName('Bob', 'Adams')
// let result3 = buildName('Bob', 'Adams', 'Sr.') // Expected 1-2 arguments, but got 3.

默认参数

// 注意有默认值的放在后面
function buildName(firstName: string, lastName = 'Smith'): string {
  return `${firstName} ${lastName}`
}
let result1 = buildName('Bob')
let result2 = buildName('Bob', 'Adams')
// let result3 = buildName('Bob', 'Adams', 'Sr.') // Expected 1-2 arguments, but got 3.

编译结果

// 注意有默认值的放在后面
function buildName(firstName, lastName): string {
    if (lastName === void 0) { lastName = 'Smith'; }
    return firstName + " " + lastName;
}
var result1 = buildName('Bob');
var result2 = buildName('Bob', 'Adams');
// let result3 = buildName('Bob', 'Adams', 'Sr.') // Expected 1-2 arguments, but got 3.

剩余参数

// 注意有默认值的放在后面
function buildName(firstName: string, ...restOfName: string[]): string {
  return ''
}
let result1 = buildName('Bob')
let result2 = buildName('Bob', 'Adams')
let result3 = buildName('Bob', 'Adams', 'Sr.') // Expected 1-2 arguments, but got 3.

this

let deck = {
  suits: ['hearts', 'spades', 'clubs', 'diamonds'],
  cards: Array(52),
  createCardPicker: function() {
    return function() {
      let pickedCard = Math.floor(Math.random() * 52)
      let pickedSuit = Math.floor(pickedCard / 13)
      return {
        suits: this.suits[pickedSuit],
        card: pickedCard % 13
      }
    }
  }
}

let cardPicker = deck.createCardPicker()
let pickedCard = cardPicker()
console.log(`card:${pickedCard.card},suit:${pickedCard.suits}`)

 改用箭头函数

let deck = {
  suits: ['hearts', 'spades', 'clubs', 'diamonds'],
  cards: Array(52),
  createCardPicker: function() {
    return () => {
      let pickedCard = Math.floor(Math.random() * 52)
      let pickedSuit = Math.floor(pickedCard / 13)
      return {
        suits: this.suits[pickedSuit],
        card: pickedCard % 13
      }
    }
  }
}

let cardPicker = deck.createCardPicker()
let pickedCard = cardPicker()
console.log(`card:${pickedCard.card},suit:${pickedCard.suits}`)

 明确this的指向

interface Card {
  card: number
  suit: string
}
interface Deck {
  cards: number[]
  suits: string[]
  createCardPicker(this: Deck) :() => Card
}

let deck: Deck = {
  suits: ['hearts', 'spades', 'clubs', 'diamonds'],
  cards: Array(52),
  createCardPicker: function(this: Deck) {
    return () => {
      let pickedCard = Math.floor(Math.random() * 52)
      let pickedSuit = Math.floor(pickedCard / 13)
      return {
        suit: this.suits[pickedSuit],
        card: pickedCard % 13
      }
    }
  }
}

let cardPicker = deck.createCardPicker()
let pickedCard = cardPicker()
console.log(`card:${pickedCard.card},suit:${pickedCard.suit}`)

this在回调函数中


interface UIElement {
  addClickListener(onclick: (this: void, e: Event) => void): void
}
class Handler {
  type: string
  onClickBad = (e: Event) => {
    this.type = e.type
  }
}

let h = new Handler()
let uiElemnet : UIElement = {
  addClickListener(){}
}
uiElemnet.addClickListener(h.onClickBad)

重载

let suits =['hearts', 'spades', 'clubs', 'diamonds']
function pickCard(x: {suit: string, card: number}[]): number
function pickCard(x: number): {suit: string, card: number}
function pickCard(x): any {
  if(Array.isArray(x)) {
    let pickCard = Math.floor(Math.random() * x.length)
    return pickCard
  } else {
    let pickedSuit = Math.floor(x / 13)
    return {
      suit: suits[pickedSuit],
      card: x % 13
    }
  }
}

let myDeck = [
  {suit: 'diamonds', card: 2},
  {suit: 'spades', card: 10},
  {suit: 'hearts', card: 4}
]
let pickCard1 = myDeck[pickCard(myDeck)]
console.log(`crad:${pickCard1.card}, suit:${pickCard1.suit}`)
let pickCard2 = pickCard(15)
console.log(`crad:${pickCard2.card}, suit:${pickCard2.suit}`)

泛型

基础用法

// T 用于捕获用户传递类型,即用户说是啥,当前上下文中以后T就是啥类型
function identity<T>(arg: T): T {
  return arg
}

// 使用
// 直接说明
let out1 = identity<string>('str')
// 类型推断
let out2 = identity('str')

function loggingIdentity<T>(arg: T[]): T[] {
  console.log(arg.length)
  return arg
}

泛型接口

function identity<T>(arg: T): T {
  return arg
}
// 泛型接口
interface GenericIdentityFn<T> {
  (arg: T): T
}
// 泛型函数类型
let myIdentity: <T>(arg: T) => T = identity

let myIdentity2: GenericIdentityFn<number> = identity

泛型类

class GenericNumber<T> {
  zeroValue: T
  add: (x: T, y: T) => T
}

let myGenericNumber = new GenericNumber<number>()
myGenericNumber.zeroValue = 0
myGenericNumber.add = function(x, y) {
  return x + y
}

let stringNumeric = new GenericNumber<string> ()
stringNumeric.zeroValue = 'Hello '
stringNumeric.add = function (x, y) {
  return x + y
}

console.log(myGenericNumber.add(myGenericNumber.zeroValue, 2020))
console.log(stringNumeric.add(stringNumeric.zeroValue, 'world'))

泛型约束

//用接口约束泛型的类型

interface Lengthwise {
  length: number
}
//用接口约束泛型的类型
function loggingIdentity<T extends Le>(arg: T): T {
  console.log(arg.length)
  return arg
}

简单应用

function getProperty<T, K extends keyof T>(obj: T, key: K) {
  return obj[key]
}

let x = {a:1}
console.log(getProperty(x, 'a'))
// console.log(getProperty(x, 'b')) // error

泛型中使用类类型(工厂函数)

function create<T>(c: {new(): T}): T {
  return new c()
}

应用

class BeeKeeper {
  hasMask: boolean
}
class LionKeeper {
  nametag: string
}
class Animal {
  numLengs: number
}
class Bee extends Animal {
  keeper: BeeKeeper
}
class Lion extends Animal {
  keeper: LionKeeper
}
function createInstance<T extends Animal> (c: new() => T): T {
  return new c()
}
createInstance(Lion).keeper.nametag
createInstance(Bee).keeper.hasMask

类型推断

class Animal {
  numLegs: number
}
class Bee extends Animal {
 
}
class Lion extends Animal {
}
// let zoo: Animal[] = [new Bee(), new Lion()] // 自己给出
let zoo = [new Bee(), new Lion()] // 类型推断

上下文类型

class Animal {
  numLegs: number
}
class Bee extends Animal {
 
}
class Lion extends Animal {
}

function createZoo(): Animal[] {
  return [new Bee(), new Lion()] // 返回值会根据函数返回值类型推断返回的是Animal数组
}

高级类型

交叉类型

// 多个类型混合为一种类型
function extend<T, U>(first: T, second: U): T&U {
  let result = {} as T&U
  for(let id in first) {
    result[id] = first[id] as any
  }
  for(let id in second) {
    if (!result.hasOwnProperty(id)) {
      result[id] = second[id] as any
    }
  }
  return result
}
class Person {
  constructor(public name: string) {
    
  }
}
interface Loggable {
  log(): void
}
class ConsoleLooger implements Loggable {
  log() {}
}
var jim = extend(new Person('jim'), new ConsoleLooger())
jim.name
jim.log()

联合类型

function padLeft(value: string, padding: string | number) {
  if (typeof padding === 'number') {
    return Array(padding + 1).join(' ') + value
  }
  if (typeof padding === 'string') {
    return padding + value
  }
}
padLeft('Hello world', 1)
padLeft('Hello world', '  ')

联合类型使用注意 —— 独有方法的使用

interface Bird {
  fly()
  layEggs()
}
interface Fish {
  swim()
  layEggs()
}
function getSmallPet(): Fish | Bird {
  //...
}
let pet = getSmallPet()
pet.layEggs()
// pet.swim() // error 使用独有方法会报错

类型保护

用户自定义 is

interface Bird {
  fly()
  layEggs()
}
interface Fish {
  swim()
  layEggs()
}
function getSmallPet(): Fish | Bird {
  //...
}
let pet = getSmallPet()
pet.layEggs()
// pet.swim() // error 使用独有方法会报错
if (isFish(pet)) {
  pet.swim()
} else {
  pet.fly()
}

// 类型保护机制 is
function isFish(pet: Fish | Bird): pet is Fish {
  return (pet as Fish).swim !== undefined
}

typeof

instanceof

可以为null的类型

null和undefined既可以为值也可为类型,并且二者都是其他所有类型的有效值

let s = 'foo'
s = null
let sn: string | null = 'bar'
sn = null
sn = undefined

null不能赋值给undefined或者联合类型

function broken(name: string | null): string {
  function postfix(epither: string) {
    return `${name!.charAt(0)}.the ${epither}`
  }
  name = name || 'Bob'
  return postfix(name)
}

字符串字面量类型

type Easing = 'ease-in' | 'ease-out' | 'ease-in-out'
class UIElemnet {
  animate(dx: number, dy: number, easing: Easing) {
    if (easing === 'ease-in') {
      //...
    } else if (easing === 'ease-out') {
    } else if (easing === 'ease-in-out') {
    } else {
    }
  }
}

let button = new UIElemnet()
button.animate(0, 0, 'ease-in')

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值