TypeScript基础篇

202 阅读4分钟

全局安装ts:npm install -g typescript

检验版本 tsc -v

ts有哪些数据类型:

  • string
  • number
  • boolean
  • undefined
  • null
  • enum
  • sysbol
  • void
  • any
  • type Name = boolean | number | "男"

ts具有类型校验功能,写错会报错但不影响编译成js及运行。


let a : string  = "2"
a = 1   报错
a = null 不会报错

因为undefined 和null属于string,number ,boolean 的子类型,

初始化未赋值的变量默认any类型

let a;      // 默认加上:any

初始化赋值的变量将按类型推断

let a = 1;      // 默认加上:number

联合类型,例:

let a:nummber | string = 1;      // number 和 string 类型都可

接口,习惯以I为首字母并大写

intefacr Istate = {
    name : string ,
    readonly isMarry : boolean      // readonly 只读
    age? : number,                  // ? 可选属性
    [propName:string] : any         // 属性数量不限
}
let a : Istate =  {
    name : "张一山",
    age:18,
    sex:"男"
}

funtion getUserInfo(user1:Istate){
    return "姓名:" + user1.name + "-年龄:" + user1.age
}

// 函数类型接口
// 接口能够描述 JavaScript 中对象拥有的各种各样的外形。 除了描述带有属性的普通对象外,接口也可以描述
// 函数类型。

// 为了使用接口表示函数类型,我们需要给接口定义一个调用签名。它就像是一个只有参数列表和返回值类型的函// // 数定义。参数列表里的每个参数都需要名字和类型。
interface SearchFunc {
  (source: string, subString: string): boolean
}
// 这样定义后,我们可以像使用其它接口一样使用这个函数类型的接口。 下例展示了如何创建一个函数类型的变// // 量,并将一个同类型的函数赋值给这个变量。

const mySearch: SearchFunc = function (source: string, sub: string): boolean {
  return source.search(sub) > -1
}

console.log(mySearch('abcd', 'bc'))


/* 
类类型: 类实现接口
1. 一个类可以实现多个接口
2. 一个接口可以继承多个接口
*/

interface Alarm {
  alert(): any;
}

interface Light {
  lightOn(): void;
  lightOff(): void;
}

class Car2 implements Alarm, Light {
  alert() {
    console.log('Car alert');
  }
  lightOn() {
    console.log('Car light on');
  }
  lightOff() {
    console.log('Car light off');
  }
}


// 接口继承接口
interface LightableAlarm extends Alarm, Light {

}

数组

// 类型 + 中括号
let arr1 : string []  = ["1","2","3"];
let arr2 : any []  = [1,"2",true];

//泛型写法

let arr3 : Array<string>  = ["1","2","3"];
let arr4 : Array<any>  = [1,"2",true];

//接口写法
interface Istate{
    name : string,
    age : number 
}

interface Iarr{
    [index: number] : Istate
}

let arr5 : Iarr = [{name:"张一山"age:12}];
let arr6 : Array<Istate>  = [{name:"张一山"age:12}];

函数

function setState(name:string, age:number, sex?:string): number{
    return age
}

// 联合函数重载
function getValue(value : string) : string;
function getValue(value : number) : number;
function getValue(value : string | number){
    return value;
}

// 表达式类型函数验证方式   name参数默认值"张一山"
let func : (name:string , age : number) => number  = function(name:string  = "张一山", age : number) : number{
    return age
}


// 类型断言(number没有.length方法,需要转换成string,断言类型仅支持联合函数中的类型)
function getLength(val : number | string){
    return (<string>val).length;
    或者(react的jsx语法的ts版仅支持下面这个)
    return (val as string).length;
}

枚举

enum names {
    "wang",
    "li",
    "zhang",
    "liu",
}
names[0] === "wang"    // true
names["wang"] === 0    // true

类*****(很重要)

类的修饰符

  • public // 默认 公有
  • private // 私有 类内部可访问
  • protected // 半私有 类内部和子类可以访问
// 例子1
class Father {
    name : "父亲"
    say(){
         console.log("我是" + super.name )
    }
}

// 继承, 用super调用父类方法,属性(包括私有属性及方法)
// java里子类不可以访问父类的私有属性或方法,

class Son extends Father {
    // 子类方法会覆盖父类同名方法
    say(){
       console.log("我是" + super.name + "的儿子")
    }
    // 静态方法不需要new,可以直接Son.go()
    static go(){
        conosle.log("让我们荡起双桨,小船儿推开波浪,海面倒映着美丽的白塔,四周环绕着绿树红墙。")
    }
}

let son1 = new Son();
son1.say();      // 我是父亲的儿子
Son.go()         // 让我们荡起双桨,小船儿推开波浪,海面倒映着美丽的白塔,四周环绕着绿树红墙。



// 例子2
class User {
  fullName: string
  firstName: string
  lastName: string

  constructor (firstName: string, lastName: string) {
    this.firstName = firstName
    this.lastName = lastName
    this.fullName = firstName + ' ' + lastName
  }
}

interface Person {
  firstName: string
  lastName: string
}

function greeter (person: Person) {
  return 'Hello, ' + person.firstName + ' ' + person.lastName
}

let user = new User('Yee', 'Huang')

console.log(greeter(user))

类继承*****

/* 
类的继承
*/

class Animal {
  run (distance: number) {
    console.log(`Animal run ${distance}m`)
  }
}

class Dog extends Animal {
  cry () {
    console.log('wang! wang!')
  }
}

const dog = new Dog()
dog.cry() 
dog.run(100) // 可以调用从父中继承得到的方法

这个例子展示了最基本的继承:类从基类中继承了属性和方法。 这里,Dog 是一个 派生类,它派生自 Animal 基类,通过 extends 关键字。 派生类通常被称作子类,基类通常被称作超类。

因为 Dog 继承了 Animal 的功能,因此我们可以创建一个 Dog 的实例,它能够 cry() 和 run()。

下面我们来看个更加复杂的例子。

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

  run (distance: number=0) {
    console.log(`${this.name} run ${distance}m`)
  }

}

class Snake extends Animal {
  constructor (name: string) {
    // 调用父类型构造方法
    super(name)
  }

  // 重写父类型的方法
  run (distance: number=5) {
    console.log('sliding...')
    super.run(distance)
  }
}

class Horse extends Animal {
  constructor (name: string) {
    // 调用父类型构造方法
    super(name)
  }

  // 重写父类型的方法
  run (distance: number=50) {
    console.log('dashing...')
    // 调用父类型的一般方法
    super.run(distance)
  }

  xxx () {
    console.log('xxx()')
  }
}

const snake = new Snake('sn')
snake.run()

const horse = new Horse('ho')
horse.run()

// 父类型引用指向子类型的实例 ==> 多态
const tom: Animal = new Horse('ho22')
tom.run()

/* 如果子类型没有扩展的方法, 可以让子类型引用指向父类型的实例 */
const tom3: Snake = new Animal('tom3')
tom3.run()
/* 如果子类型有扩展的方法, 不能让子类型引用指向父类型的实例 */
// const tom2: Horse = new Animal('tom2')
// tom2.run()

抽象类

抽象类做为其它派生类的基类使用。 它们不能被实例化。不同于接口,抽象类可以包含成员的实现细节。 abstract 关键字是用于定义抽象类和在抽象类内部定义抽象方法。

/* 
抽象类
  不能创建实例对象, 只有实现类才能创建实例
  可以包含未实现的抽象方法
*/

abstract class Animal {

  abstract cry ()

  run () {
    console.log('run()')
  }
}

class Dog extends Animal {
  cry () {
    console.log(' Dog cry()')
  }
}

const dog = new Dog()
dog.cry()
dog.run()

泛型

function creatArr<T>(val:T):Array<T>{
    // 一顿操作
    let a : Array<T> = [] 
    return a;
}
let strNum : Array<number> = creatArr(1)        // true
let strNum2 : Array<number> = creatArr("1")     // false

让我们荡起双桨,小船儿推开波浪,海面倒映着美丽的白塔,四周环绕着绿树红墙。