typescript筆記

深入淺出typescript

在Youtube上看視頻學了一下typescript,主要爲了接下來讀源碼方便。

primitive類型的用小寫。少用object/any。可以直接用[key: string]這樣的方式去定義規範。

interface Person {
  readonly sex: string;
  [key: string] : string | number;
}

const a: Person = {
  sex: 'man',
  name: 'as',
  foo: 2
}

class 語法, implements與extends

interface Person {
  name: string;
  address?: string;
  sayHi: Function
}

class Patient implements Person {
  name: string;
  address?: string | undefined;
  constructor ( name: string, addressCode?: number) {
    this.name = name
    this.address = 'nation:' + (addressCode || 'empty')
  }
  sayHi = () => {
    console.log(this.name + ' say hey')
  }
}

class BadPatient extends Patient {
  age: number
  constructor ( name:string, age:number, addressCode?:number ) {
    super(name, addressCode)
    this.age = age
  }
  sayHi = () => {
    console.log(this.name + ' is ' + this.age)
  }
}

const xiaoMing = new BadPatient( 'xiaoming',23, 32 )

console.log(xiaoMing)


class Greeter<A> {
  private greeting: A

  constructor ( message: A ) {
    this.greeting = message
  }
  public greet() {
    console.log(`hello ${this.greeting}`)
  }
}

const a = new Greeter<string>( 'miya' )

對函數也可以定義多個type。

interface add {
  ( a: number, b: number ): number
}

interface add {
  ( a: string, b: string ): string
}

const addFunc: add = ( s: any, d: any ) => s + d

console.log(addFunc( '2', '32' ))

console.log(addFunc(2, 32))

擴展類型

interface Lengthwise {
  length: number,
  0: number
}

function loggingIdentity<T extends Lengthwise>( arg: T ): T {
  console.log( arg.length, arg[ 0 ].toExponential() )
  return arg
}

loggingIdentity([9.234])

module可以在tsconfig裏配,正常import export即可。node8之後實驗性地支持es6。

node --experimental-modules bar.mjs

namespace編譯後其實就是一個object。類似沙箱。處理衝突。

namespace lala {
  function foo( a: string ): number {
    return a.length
  }
  let name:string = 'sdsd'
}

// 編譯後:
(function (lala) {
    function foo(a) {
        return a.length;
    }
    var name = 'sdsd';
})(lala || (lala = {}));

decorators,多用於class內的方法或屬性。也可以用於整個class

function log( target: any, key: any, descriptor: any ) {
  const original = descriptor.value
  if ( typeof original === 'function' ) {
    descriptor.value = function () {
      const result = original.apply( this, arguments )
      console.log( {result})
    }
  }
  return descriptor
}

class Foo {
  @log
  greet( a: void ): string {
    return 'hello'
  }
}

const b = new Foo()
b.greet()

// T has to be in construtor form so the fucntion know how to extends it
function init<T extends { new( ...args: any[] ): {} }>( constructor: T ): T {
  return class extends constructor {
    firstName = 'mengge'
    lastName = 'xue'
  }
}

@init
class Coder{
  firstName: string = ''
  lastName: string =  ''
}

const a = new Coder()
console.log(a.firstName, a.lastName, a instanceof Coder)

mixins

class Swimer {
  speed = 10
  swim( distance: number ): number {
    return distance * this.speed
  }
}

class Runner {
  speed = 10
  run( distance: number ): number {
    console.log(distance, this.speed, '---')
    return distance * this.speed * 10
  }
}

class Person implements Swimer, Runner {
  speed = 2
  swim( distance?:number ) {
    return -2
  }
  run( distance?: number ) {
    console.log(distance)
    return 1200
  }
}
function applyMixins( derivedCtor: any, baseCtors: any[] ) {
  baseCtors.forEach( baseCtor => {
    Object.getOwnPropertyNames( baseCtor.prototype ).forEach( name => {
      derivedCtor.prototype[ name ] = baseCtor.prototype[ name ]
    } )
  } )
}
applyMixins( Person, [ Swimer, Runner ] )

const person = new Person()
console.log(person.run(12), person.speed)

type和type也可以和或並。

interface Person {
  name: string
  sayHi?: Function
}

interface Animal {
  type: string
}

type Kitty = Person & Animal

const cat: Kitty = {
  name: 'kemo',
  type: 'cat'
}

this type。this也是一種特殊的類型。函數中返回this,可以用於鏈式函數。

class BasicCalculator {
  // 這裏加上protected之後,constructor裏等於寫了this.value = value
  public constructor ( protected value: number = 0 ) { }
  public currentValue(): number {
    return this.value
  }
  public add( operand: number ): this {
    this.value += operand
    return this
  }

  public multiply( operand: number ): this {
    this.value *= operand
    return this
  }
}

const c = new BasicCalculator( 2 )

console.log(c.add(20).multiply(3).currentValue())

mapped types 快捷寫法,利用已有的type,生成相應的特殊type。在react/angular中很有用

/*
in lib.es5.d.ts
type Readonly<T> = {
  readonly [p in keyof T]: T[P]
}
type Partial<T> = {
  [P in keyof T]?: T[P]
}
*/
type Person = {
  name: string,
  age: number
}

type PersonPartial = Partial<Person>

type ReadonlyPerson = Readonly<Person>

const zhenzhen: ReadonlyPerson = {
  name: 'zhenzhen',
  age: 12
}

// zhenzhen.age = 23 cannot assign to 'age' cause it is readonly

// pick
type Pick<T, K extends keyof T> = { [P in K]: T[P] }
type ColorDuck = Pick<Duck, 'color>
// = {color: string}

async function fetchUserById<T extends keyof Person>(id: string, ...fields: T[]): Promise<Pick<Reaction, T>> {
  return await kenx('User').where({id}).select(fields).first()
}
declare function f<T extends boolean>( x: T ): T extends true ? string : number 

let x = f(Math.random() < 0.5)

type StringOrNumber<T> = T extends boolean? string : number
type T1 = StringOrNumber<true> // string
type T2 = StringOrNumber<object> //number
type ElementType<T> = T extends (infer U)[]? U: never
type T = ElementType<[]> // never
type T1 = ElementType<string[]> // string

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章