ts入门学习

ctrl+k清屏

1.ts入门

1.安装VSCode

​ https://code.visualstudio.com/Download
2.安装Node.js为了安装npm

​ https://nodejs.org/en/download/

3.安装TypeScript编译器:npm install -g typescript

可以用tsc 文件.ts命令,根据ts生成js代码

node 文件.js 运行js

4.ts介绍

​ TypeScript 是 JavaScript 的类型的超集,是一种静态类型检查的语言,提供了类型批注和编译时类型检查;支持ES6语法,支持面向对象编程的概念,如类、接口、继承、泛型等; TypeScript 在编译阶段需要编译器编译成纯 JavaScript 来运行。

  1. ts和js的语言区别
    js是脚本语言,ts是面向对象语言
    js弱类型,ts强类型
    ts增加了类和接口
2.优化编译

1.解决ts和js的冲突问题(比如命名)

​ tsc --init #生成配置文件 tsconfig.json

2.自动编译

​ tsc --watch

3.发出错误

​ tsc -noEmitOnError 文件.ts 提示错误并且不自动编译程js

3.tsconfig配置-修改完重新编译

​ tsconfig.json----“target”:“es5” 降级编译(考虑旧版本浏览器兼容)

​ strict:true 包含下面两种。是否忽略类型验证(false就会默认为any,破坏了ts类型检查)

​ noImplicitAny:true :不含隐藏的any(any检查,不用默认any)

​ strictNullChecks:true;严格空类型检验

​ strictPropertyInitialization:false:是否属性必须初始化(定义class),false不会检查属性

​ rootDirs|rootDir:ts目录

​ outDir:js输出目录

4.类型
  • boolean(布尔类型)

  • number(数字类型)

  • string(字符串类型)

  • 数组:type[]、Array泛型

  • any:不希望某个特定值导致类型检查错误

  • null 类型数据加一个!可以排除null和undefined

  • undefined 类型数据加一个!可以排除null和undefined

  • enum Name {} 枚举-一组数值赋予友好的名字

  • void 不返回任何值

    一个具有 void返回类型的上下文函数类型(type vf = () => void),在实现时,可以返回任何其他的值,但它会被忽略。

    当一个字面的函数定义有一个 void 的返回类型时,该函数必须不返回任何东西。

  • object:任何不是基元的值:string\number\bigint\boolean\symbol\null\undefined;不同于{},不同于Object

  • unknown:代表任何值。这与 any 类型类似,但更安全,因为对未知 unknown 值做任何事情都是不合法的

  • never: 是其他类型 (包括null和 undefined)的子类型,可以赋值给任何类型,代表从不会出现的值,类型表示永远不会被观察到的值(抛出异常|永远不触发)

  • Function :全局性的 Function 类型描述了诸如 bind、call、apply和其他存在于JavaScript中所有函数值的属性。它还有一个特殊的属性,即 Function 类型的值总是可以被调用;这些调用返回 any

  • tuple(元组类型):表示一个已知元素数量和类型的数组,各元素的类型不必相同。

  • enum(枚举类型):一组数值赋予友好的名字

5.类型相关注意
  • : type 类型注释。可以指定具体字符、数字、true(文字类型 --有时候配合类型推断时使用)

  • ?: type 可选类型 不传是undefined 调用方法可以用?.。可选属性使用时候在后面加个!表示肯定存在的

  • {x: numbr,y: number}对象

  • number | string 一个竖线-联合类型

  • type name = type 类型别名,name一般大写

  • 类型判断 typeof对象的时候。排除null strs&&typeof

  • !:

    • 属性或参数中使用 !:——表示强制解析(告诉typescript编译器,这里一定有值),常用于vue-decorator中的@Prop
    • 变量后使用 !:——表示类型推断排除null、undefined
  • keyof 类型操作符

    type Point = { x: number; y: number };
    type P = keyof Point;//这时候p是’x’|'y’联合类型
    const p1:P = ‘x’
    const p2:P = ‘y’

  • 在泛型约束中使用类型参数:key extends keyof Type

    function getProperty<Type, Key extends keyof Type>(obj: Type, key: Key) {
      return obj[key]
    }
    let x = {
      a: 1, 
      b: 2,
      c: 3,
      d: 4
    }
    getProperty(x, 'a')
    
  • in用来类型缩小

    type Fish = { swim: () => void }
    type Bird = { fly: () => void }
    type Human = { swim?: () => void; fly?: () => void }
    
    function move(animal: Fish | Bird | Human) {
      if ("swim" in animal) {
        // animal: Fish | Human
        return (animal as Fish).swim()
      }
    
      // animal: Bird | Human
      return (animal as Bird).fly()
    }
    
  • 不太常用的原语

    const oneHundred: bigint = BigInt(100)
    const anotherHundred: bigint = 100n //target:es2020才能使用
    const firstName = Symbol("name")
    const secondName = Symbol("name")
    
    if (firstName === secondName) {
      console.log('ok')
    }
    
  • as type; 类型断言(用来转成更具体或者不太具体的版本,可以防止不可能的强制的发声)。会在编译时被删除,没有与类型断言相关联的类型检查。

//返回某种类型的HTMLElement
const myCanvas = document.getElementById ("main_canvas") as HTMLCanvasElement
const myCanvas = <HTMLCanvasElement>document.getElementById ("main_canvas")
const x = 'hello' as any
const y = 'hello' as unknown
6.接口(一般接口能实现,类型别名都可以)

类型别名创建后不能通过同一个名称扩展

  • 类型使用(接口定义类型)

    interface Point {
      x: number;
      y: number;
    }
    function printCoord(pt: Point) {
      console.log("坐标x的值是: " + pt.x);
      console.log("坐标y的值是: " + pt.y);
    }
    printCoord({ x: 100, y: 100 });
    
  • 扩展接口

    interface Animal {
      name: string
    }
    interface Bear extends Animal {
      honey: boolean
    }
    const bear: Bear = {
      name: 'winie',
      honey: true
    }
    console.log(bear.name)
    console.log(bear.honey)
    

    类型别名实现接口扩展效果

    //交叉点实现即&
    type Animal = {
      name: string
    }
    type Bear = Animal & {
      honey: boolean
    }
    const bear: Bear = {
       name: 'winnie',
       honey: true
    }
    
  • 向现有接口类型添加字段

    //向现有的类型添加字段,会起到合并效果
    interface MyWindow {
      count: number
    }
    interface MyWindow {
      title: string
    }
    const w: MyWindow = {
      title: 'hello ts',
      count: 100
    }
    

    ​ 类型别名创建后不能通过同一个名称扩展

7.函数
  • 普通定义函数类型:type GreetFunction = (a: string) => void

  • 调用签名定义函数类型(对象方式定义)

    type DescribableFunction = {
    description: string //函数属性-函数可以直接调用
    (someArg: number): boolean //入参(string)=>返回类型(boolean)
    }

    //如上类型的函数

    function fn1(n: number) {
    console.log(n)
    return true
    }
    fn1.description = ‘hello’

  • 构造签名

    需要new

    class Ctor {
    s: string
    constructor(s: string) {
    this.s = s
    }
    }

    type SomeConstructor = {
    new (s: string): Ctor
    }

    function fn(ctor: SomeConstructor) {
    return new ctor(‘hello’)
    }

    interface CallOrConstructor {
    new (s: string): Date
    (n?: number): number
    }

    function fn(date: CallOrConstructor) {
    let d = new date(‘2021-12-20’) //构造签名
    let n = date(100) //调用签名
    }

  • 泛型

    编写优秀函数的三个准则

    1.尽量使用本身,而不是类型约束;

    2.尽量少的使用类型参数;

    3.类型参数是用来关联多个值的类型的,类型如果只使用一次,每笔用用泛型

    1. 类型判断 ,<Type1,Type2> 尽量只使用本身

      function firstElement(arr: Type[]): Type | undefined {
      return arr[0]
      }

      firstElement([‘a’, ‘b’, ‘c’])
      firstElement([1, 2, 3])
      firstElement([])

    2. 限制条件 <Type extends { length: number }>类型必须有length属性

      function longest<Type extends { length: number }>(a: Type, b: Type) {
      if (a.length >= b.length) {
      return a
      } else {
      return b
      }
      }

      const longerArray = longest([1, 2], [2, 3, 4])

    3. 指定类型参数 <string | number> 不推荐,指定第一个是string,第二个是number

      function combine(arr1: Type[], arr2: Type[]): Type[] {
      return arr1.concat(arr2)
      }

      const arr = combine<string | number>([“string”], [1, 2, 3])

      console.log(arr)

  • 可选参数

    ?: 可选参数;默认值:number=100

    为回调写一个函数的时候,永远(尽量)不要写可选参数

  • 函数重载

    函数重载定义如何调用,函数实现才是真正的函数实现,函数实现参数得兼容函数重载

    编写好的重载

    总是倾向于使用联合类型的参数而不是重载参数

    //函数重载 function makeDate(timestamp: number): Date
    //函数重载 function makeDate(m: number, d: number, y: number): Date

    //函数实现 function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
    if (d !== undefined && y !== undefined) {
    return new Date(y, mOrTimestamp, d)
    } else {
    return new Date(mOrTimestamp)
    }
    }

    const d1 = makeDate(12345678)
    const d2 = makeDate(5, 6, 7)
    const d3 = makeDate(5, 9) //报错

  • rest parameters 形参展开方式

    //形参展开

    function multiply(n: number, …m: number[]) {
    return m.map( x => n * x )
    }

    const a = multiply(10, 1, 2, 3, 4, 60, 100)

    console.log(a)

    //实参展开

    const arr1 = [1, 2, 3]
    const arr2 = [4, 5, 6]
    arr1.push(…arr2)

    // const args = [8, 5]
    // const angle = Math.atan2(…args) //报错

    const args = [8, 5] as const
    const angle = Math.atan2(…args)

    //参数结构

    type ABC = { a: number, b: number, c: number }

    function sum({ a, b, c }: ABC) {
    console.log(a + b + c)
    }

    sum({
    a: 10,
    b: 3,
    c: 9
    })

  • void

    一个具有 void返回类型的上下文函数类型(type vf = () => void),在实现时,可以返回任何其他的值,但它会被忽略。

    当一个字面的函数定义有一个 void 的返回类型时,该函数必须不返回任何东西。

    type voidFunc = () => void

    const f1:voidFunc = () => {
    return true
    }

    const f2:voidFunc = () => true

    const f3:voidFunc = function() {
    return true
    }

    const v1: void = f1()
    const v2 = f2()
    const v3 = f3()

    // 下面会报错

    function f4(): void {
    return true
    }

    const f5 = function(): void {
    return true
    }

8.对象类型
  • 定义

    //匿名方式定义对象类型
    function greet(person: { name: string, age: number }) {
      return 'Hello ' + person.name
    }
    //接口方式
    interface Person {
      name: string
      age: number
    }
    
    function greet(person: Person) {
      return 'Hello ' + person.name
    }
    //类型别名
    type Person = {
      name: string
      age: number
    }
    
    function greet(person: Person) {
      return 'Hello ' + person.name
    }
    
  • 属性修改器

    可选属性 :配合默认值

    interface PaintOptions {
    xPos?: number,
    yPos?: number
    }

    function paintShape({ xPos: number = 0, yPos = 0 }: PaintOptions) {
    // let xPos = opts.xPos === undefined ? 0 : opts.xPos
    // let yPos = opts.yPos === undefined ? 0 : opts.yPos
    console.log(number)
    }

    只读属性:readonly

    ​ 加了readonly不能修改,引用对象是不能修改引用地址

    ​ readonly类型可以复制可写类型

    索引签名:不能知道一个类型的所有属性名称

    //索引签名只有number和string
    interface StringArray {
      [index: number]: string
    }
    
    const myArray: StringArray = ['a', 'b']
    const secondItem = myArray[0]
    
    interface TestString {
      [props: string]: number
    }
    
    let testString: TestString = {
      x: 100,
      y: 200,
      // aaa: 'aaa'
    }
    
    interface NotOkay {
      [index: string]: number | string
      length: number
      name: string
    }
    
    let notOkay: NotOkay = {
      x: 100,
      length: 100,
      name: 'felix'
    }
    
  • 扩展类型

    interface Colorful {
      color: string
    }
    interface Circle {
      radius: number
    }
    
    interface ColorCircle extends Colorful, Circle {}
    const cc: ColorCircle = {
      color: 'red',
      radius: 100
    }
    
  • 交叉类型

    interface Colorful {
      color: string
    }
    
    interface Circle {
      radius: number
    }
    
    type ColorfulCircle = Colorful & Circle
    const cc: ColorfulCircle = {
      color: 'red',
      radius: 100
    }
    
  • 扩展类型和交叉类型主要区别

    interface可以重名合并,类型别名可以避免命名冲突

  • 泛型类型对象

    // interface Box<Type> {
    //   contents: Type
    // }
    // 通用类型 以下写法很好
    type OrNull<Type> = Type | null
    type OneOrMany<Type> = Type | Type[]
    type OneOrManyOrNull<Type> = OrNull<OneOrMany<Type>>
    type OneOrManyOrNullString = OneOrManyOrNull<string>
    
9.从类型中创建类型
  • 泛型*

    function identity<Type>(arg: Type): Type {
      return arg
    }
    identity<string>("string")
    identity("string")
    //泛型类型
    let myIdentity: <Type>(arg: Type) => Type = identity
    let myIdentity: <Input>(arg: Input) => Input = identity
    let myIdentity: { <Type>(arg: Type): Type } = identity
    
    interface GenericIdentityFn {
       <Type>(arg: Type): Type
    }
    let myIdentity: GenericIdentityFn = identity
    
    interface GenericIdentityFn<Type> {
      (arg: Type): Type
    }
    let myIdentity: GenericIdentityFn<string> = identity 
    
    //泛型类
    class GenericNumber<NumType> {
      zeroValue: NumType
      add: (x: NumType, y: NumType) => NumType
    }
    
    let myGeneric = new GenericNumber<number>()
    myGeneric.zeroValue = 0
    myGeneric.add = function (x, y) {
      return x + y
    }
    
    //泛型约束
    类型必须有extends里面的属性
    interface Lengthwise {
      length: number
    }
    //Type必须有length属性
    function loggingIdentity<Type extends Lengthwise>(arg: Type): Type {
      arg.length
      return arg
    }
    
    loggingIdentity(['hello', 'world'])
    
    //在泛型约束中使用类型参数
    key extends keyof Type
    key类型一定属于Type类型的某个key
    function getProperty<Type, Key extends keyof Type>(obj: Type, key: Key) {
      return obj[key]
    }
    let x = {
      a: 1, 
      b: 2,
      c: 3,
      d: 4
    }
    getProperty(x, 'a')
    
    //在泛型中使用类类型
    c是个类类型
    c: { new (): Type }
    function create<Type>(c: { new (): Type }): Type {
      return new c()
    }
    class BeeKeeper {
      hasMask: boolean = true
    }
    class ZooKeeper {
      nametag: string = 'Mikle'
    }
    class Animal {
      numLegs: number = 4
    }
    class Bee extends Animal {
      keeper: BeeKeeper = new BeeKeeper()
    }
    class Lion extends Animal {
      keeper: ZooKeeper = new ZooKeeper()
    }
    
    function createInstance<A extends Animal>(c: new () => A): A {
      return new c()
    }
    
    createInstance(Lion).keeper.nametag
    createInstance(Bee).keeper.hasMask
    createInstance(BeeKeeper)//类型约束不是没有Animal的属性
    
  • keyof 类型操作符

    // type Point = {
    //   x: number,
    //   y: number
    // }
    
    // type P = keyof Point
    
    // const p1:P = 'x'
    // const p2:P = 'y'
    // const p3:P = 'z'
    
    type Arrayish = {
      [n: number]: unknown
    }
    type A = keyof Arrayish
    const a:A = 0
    
    type Mapish = {
      [k: string]: boolean  //索引类型是string可以是number或者string
    }
    
    type M = keyof Mapish
    
    const m1:M = 's'
    const m2:M = 100
    
  • typeof类型操作符

    let s = 'hello'
    let n: typeof s  //返回s类型
    n = 'hello'
    n = 100
    
    // type Predicate = (x: unknown) => boolean
    // type K = ReturnType<Predicate>
    // function f() {
    //   return {
    //     x: 10,
    //     y: 3
    //   }
    // }
    // type P = ReturnType<typeof f>  //类型是{x:number,y:number}
    
  • 索引访问类型 //索引的时候只能使用类型

    // type Person = {
    //   age: number,
    //   name: string,
    //   alive: boolean
    // }
    
    // type Age = Person['age']
    // let age: Age = '90'
    
    
    interface Person {
      name: string
      age: number
      alive: boolean
    }
    
    // type I1 = string | number
    type I1 = Person['age' | 'name']
    const i11: I1 = 100
    const i12: I1 = ''
    // const i13: I1 = true
    
    // type I2 = string | number | boolean
    type I2 = Person[keyof Person]
    const I21: I2 = ''
    const I22: I2 = 100
    const I23: I2 = true
    // const I24: I2 = {}
    
    type AliveOrName = 'alive' | 'name'
    type I3 = Person[AliveOrName]
    const I31: I3 = true
    const I32: I3 = 'hello'
    // const I33: I3 = 100
    
    // type I4 = Person['alve']
    
    
    const MyArray = [
      { name: 'Alice', age: 15 },
      { name: 'Bob', age: 23 },
      { name: 'Eve', age: 38 }
    ]
    
    // type Person = { name: string, age: number }
    type Person = typeof MyArray[number]
    const p:Person = {
      name: 'xiaoqian',
      age: 11,
      // alive: true
    }
    
    type Age = typeof MyArray[number]['age']
    const age: Age = 11
    
    type Age2 = Person['age']
    const age2: Age2 = 300
    
    
    // const key = 'age'
    type key = 'age'
    type Age3 = Person[key]
    
  • 条件类型

    interface Animal {
      live(): void
    }
    
    interface Dog extends Animal {
      woof(): void
    }
    
    // type Example1 = number
    type Example1 = Dog extends Animal ? number : string
    
    // type Example2 = string
    type Example2 = RegExp extends Animal ? number : string
    
    条件类型约束
    // type MessageOf<T> = T['message']
    // type MessageOf<T extends { message: unknown }> = T['message']
    type MessageOf<T> = T extends { message: unknown } ? T['message'] : never
    interface Email {
      message: string
    }
    interface Dog {
      bark(): void
    }
    // type EmailMessageContents = string
    type EmailMessageContents = MessageOf<Email>
    const emc: EmailMessageContents = 'balabala...'
    type DogMessageContents = MessageOf<Dog>
    const dmc: DogMessageContents = 'error' as never
    
    //在条件类型内推理 infer
    type GetReturnType<Type> = Type extends (...args: never[]) => infer Return
        ? Return
        : never
    
    // type Num = number
    type Num = GetReturnType<() => number>
    let num: Num = 100
    
    // type Str = string
    type Str = GetReturnType<(x: string) => string>
    let str: Str = ''
    
    // type Bools = boolean[]
    type Bools = GetReturnType<(a: boolean, b: boolean) => boolean[]>
    let bools: Bools = [true, false]
    
    // type Never = never
    type Never = GetReturnType<string>
    let nev: Never = 'error' as never
    
  • 分布式条件类型

    type ToArray<Type> = Type extends any ? Type[] : never
    // type StrArrOrNumArr = string[] | number[]
    type StrArrOrNumArr = ToArray<string | number>
    let saon: StrArrOrNumArr = [1,2,3]
    
    type ToArrayNonDist<Type> = [Type] extends [any] ? Type[] : never
    //type StrArrOrNumArr = (string | number)[]
    type StrArrOrNumArr = ToArrayNonDist<string | number>
    let saon: StrArrOrNumArr = [1,'22']
    
10.类
  • 类属性

    class Point {
      x
      y
    
      constructor() {
        this.x = 0
        this.y = 0
      }
    }
    
    const pt = new Point()
    pt.x = 1
    pt.y = 1
    
    console.log(pt.x)
    console.log(pt.y)
    
    class OkGreeter {
      name!: string//类型断言可以不初始化.表示强制解析(告诉ts编译器,这里一定有值)
    }
    
  • readonly

    class Greeter {
      readonly name: string = 'world'//只可以在构造器初始化
      constructor(otherName?: string) {
        if (otherName !== undefined) {
          this.name = otherName
        }
      }
      err() {
        // this.name = 'not ok'
      }
    }
    const g = new Greeter('hello')
    // g.name = 'a'
    
  • 构造器

    class Point {
      x: number
      y: number
    
      constructor (x: number = 0, y: number = 0) {
        this.x = x
        this.y = y
      }
    }
    
  • 方法

    类内部读取属性要加this
    class Point {
      x: number = 10
      y: number = 10
    
      scale(n: number): void {
        this.x *= n
        this.y *= n
      }
    }
    
    const p = new Point()
    p.scale(10)
    console.log(p.x)
    console.log(p.y)
    
  • Getters / Setters

    如果存在 get,但没有set,则该属性自动是只读的
    如果没有指定setter参数的类型,它将从getter的返回类型中推断出来
    访问器和设置器必须有相同的成员可见性

    class C {
      _length = 0
    
      get length() {
        return this._length
      }
    
      set length(value) {
        this._length = value
      }
    }
    
    let c: C = new C()
    console.log(c.length)
    c.length = 100
    c.length = 'hello'
    console.log(c.length)
    
  • 索引签名

    class MyClass {
      [s: string]: boolean | ((s: string) => boolean)
    	//属性
      x = true
    	//函数
      check(s: string) {
        return this[s] as boolean
      }
    }
    
  • 类继承-implements子句

    //实现类型不一定与接口类型一致;可选属性可以不实现
    interface Checkable {
      check(name: string) : boolean
    }
    
    class NameChecker implements Checkable {
    //check(s: string|number) {
      check(s: string) {
        return s.toLowerCase() === 'ok'
      }
    }
    
  • extends

    //基类
    class Animal {
      move() {
        console.log('Moving along!')
      }
    }
    //派生类,基类的子类型
    class Dog extends Animal {
      woof(times: number) {
        for (let i = 0; i < times; i++) {
          console.log('woof!')
        }
      }
    }
    
    const d = new Dog()
    d.move()
    d.woof(3)
    
  • 方法重写

    //派生类是基类的子对象|子类型
    //派生类同名方法覆盖基类方法。
    //派生类一定要和基类做兼容。
    //greet(name: string)这样子就不兼容基类
    class Base {
      greet() {
        console.log('Hello World')
      }
    }
    
    class Derived extends Base {
      greet(name?: string) {
        if (name === undefined) {
          super.greet()
        } else {
          console.log(name.toUpperCase())
        }
      }
    }
    const d = new Derived()
    d.greet()
    d.greet('reader')
    //派生类是基类的子对象|子类型
    const b: Base = d
    
  • 初始化顺序

    基类的字段被初始化
    基类构造函数运行
    派生类的字段被初始化
    派生类构造函数运行

  • 继承内置类型

    //es5兼容性解决
    class MsgError extends Error {
      constructor(m: string) {
        super(m)
    
        // 明确的设置原型 
        Object.setPrototypeOf(this, MsgError.prototype)
      }
      sayHello() {
        return 'hello ' + this.message
      }
    }
    const msgError = new MsgError('hello')
    console.log(msgError instanceof MsgError)
    
  • 成员的可见性

    public(默认):公开的,默认值。任何对象在任何地方都可以访问(类内部,子类,实例上)

    protected:受保护的。能在当前类或者子类中进行访问

    ​ 子类中可以修改父类中某个属性的可见性

    class Base {
      protected m = 10
    }
    
    class Derived extends Base {
      public m = 15
    }
    
    const d = new Derived()
    console.log(d.m)
    

    private:私有的。只能在当前类中进行访问,不允许子类、实例访问

  • 静态成员

    不需要实例化,直接通过类名访问。

    静态成员可以继承,可以配合可见性使用

    class MyClass {
      private static x = 0
    
      static printX() {
        console.log(MyClass.x)
      }
    }
    
    console.log(MyClass.x)
    MyClass.printX()
    
    class Base {
      static getGreeting() {
        return 'hello world'
      }
    }
    class Derived extends Base {
      myGreeting = Derived.getGreeting()
    }
    
  • 类里的static区块

    //仅能类内部使用
    class Foo {
      static #count = 0
    
      get count() {
        return Foo.#count
      }
    
      static {
        try {
          const lastInstance = {
            length: 100
          }
          Foo.#count += lastInstance.length
        }
        catch {}
      }
    }
    //以下调用报错
    //Foo.#count
    
  • 泛型类

    静态成员不能赋值泛型

    class Box<Type> {
      contents: Type;
      constructor(value: Type) {
        this.contents = value;
      }
    }
    const b = new Box("hello!")
    
  • 类运行时候的this

    // 解决this指向问题:1.箭头函数(得保证this正确;比较耗内存,类实例得有副本;不能在派生类中使用super调用父类方法,原型链中无法获取基类方法);2.this参数(每个类定义只有一个函数被分配,而不是每个实例创建一个函数;可以super调用)
    class MyClass {
      name = 'MyClass'
      //getName() {
      // return this.name
      //}
      // getName = () => { //解决方案1
      //   return this.name
      // }
      //getName(this: MyClass) {//解决方案2//谁调用就访问谁
      //  return this.name
      //}
    }
    const c = new MyClass()
    // console.log(c.getName()) //'MyClass'
    // const obj = {
    //   name: 'obj',
    //   getName: c.getName
    // }
    // console.log(obj.getName())//'obj'
    const g = c.getName  
    // console.log(c.getName())
    console.log(g())
    
  • this类型

    派生类后基类的this依旧指向派生类

  • 基于类型守卫的this

    this is Type ;this配合守卫可以缩小类型

    class FileSystemObject {
      isFile(): this is FileRep {
        return this instanceof FileRep
      }
    
      isDirectory(): this is Directory {
        return this instanceof Directory
      }
    
      isNetworked(): this is Networked & this {
        return this.networked
      }
    
      constructor (public path: string, private networked: boolean) {}
    }
    
    class FileRep extends FileSystemObject {
      constructor(path: string, public content: string) {
        super (path, false)
      }
    }
    
    class Directory extends FileSystemObject {
      children: FileSystemObject[]
      constructor() {
        super('', false)
        this.children = []
      }
    }
    
    interface Networked {
      host: string
    }
    
    const fso: FileSystemObject = new FileRep('foo/bar.txt', 'foo')
    if (fso.isFile()) {
      // const fso: FileRep
      fso.content
    } else if (fso.isDirectory()) {
      // const fso: Directory
      fso.children
    } else if (fso.isNetworked()) {
      // const fso: Networked & FileSystemObject
      fso.host
    } 
    
    
    class Box <T> {
      value?: T
    
      hasValue(): this is { value: T } {
        return this.value !== undefined
      }
    }
    const box = new Box()
    box.value ='hello'
    
    if (box.hasValue()) {
      console.log(box.value)
    } 
    
  • 参数属性

    构造函数入参属性前加入修饰符:public readonly,protectd,private

    class Params {
      constructor (public readonly x: number, protected y: number, private z: number) {
        this.x = x
      }
    }
    
    const p = new Params(100, 300, 400)
    console.log(p.x)
    // p.x = 200
    //p.y
    //p.z 
    
  • 类表达式

    const someClass = class<Type> {
      content: Type
    
      constructor(value: Type) {
        this.content = value
      }
    }
    
    const m = new someClass('hello')
    console.log(m.content)
    
  • 抽象类和成员

    abstract:没有提供实现的方法或者字段,这些成员必须存在于一个抽象类中不能直接实例化,抽象类的作用是作为子类的基类,实现所有抽象成员。

    当一个类没有抽象成员时,我们就说他是具体的。

    abstract class Base {
      abstract getName(): string
    
      printName() {
        console.log(this.getName())
      }
    }
    
    class Derived extends Base {
      getName () {
        return 'world'
      }
    }
    
    const b = new Derived()
    b.getName()
    b.printName()
    
    function greet(ctor: new() => Base) {
      const instance = new ctor()
      instance.printName()
    }
    
    greet(Derived)
    
  • 类之间的关系

    //类属性和类型一样
    class Point1 {
      x = 0
      y = 0
    }
    
    class Point2 {
      x = 0
      y = 0
    }
    
    const p: Point1 = new Point2()
    //Emplyee 是 Person子类
    class Person {
      name: string = ''
      age: number = 100
    }
    
    class Emplyee {
      name: string = 'felixlu'
      age: number = 23
      salary: number = 10
    }
    
    const p: Person = new Emplyee()
    
11.模块

在TypeScript中编写基于模块的代码时,有三个主要方面需要考虑:
语法:我想用什么语法来导入和导出东西?
模块解析:模块名称(或路径)和磁盘上的文件之间是什么关系?
模块输出目标:我编译出来的JavaScript模块应该是什么样子的?

  • es模块化

    //导出1
    export default function helloWorld() {
      console.log('Hello, World')
    }
    
    //导出2
    export var pi = 3.14
    export let squareTwo = 1.41
    export const phi = 1.61
    export class RandomNumberGenerator {}
    export function absolute(num: number) {
      if (num < 0) return num * -1
      return num 
    }
    
    //导入
    import hello from './hello'
    import { pi, phi, absolute } from './maths'
    
    hello()
    
    console.log(pi)
    console.log(absolute(phi))
    
  • 额外的导入语法

    //导出
    export const pi = 3.14
    export default class RandomNumberGenerator {}
    //导入起别名
    import RNGen, { pi as π } from './maths'
    //import * as math from './maths'
    
    
    const rnGen = new RNGen()
    //console.log(math.pi)
    //const rnGen = new math.default()
    
  • typeScript特定的es模块语法

    //导出
    export type Cat = {
      breed: string
      yearOfBirth: number
    }
    
    // export type Dog = {
    //   breeds: string[]
    //   yearOfBirth: number
    // }
    
    export const createCatName = () => 'fluffy'
    
    export interface Dog {
      breeds: string[]
      yearOfBirth: number
    }
    //导入
    import type { Cat, Dog } from './animal'
    import { createCatName } from './animal'
    import { createCatName, type Cat, type Dog } from './animal'
    
    type Animals = Cat | Dog
    
    createCatName()
    
  • commonJs语法

    //导出module.exports;exports
    function absolute(num: number) {
      if(num < 0) return num * -1
      return num
    }
    
    module.exports = {
      pi: 3.14,
      squareTwo: 1.41,
      phi: 1.61,
      absolute
    }
    
    // exports.absolute = absolute
    //导入
    const maths = require('./maths')
    console.log(maths.pi)
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值