typescript的使用(一)

96 阅读7分钟

基础数据类型

// 变量需声明是什么类型的,并且不能赋值与该类型不同的值

//当所有ts文件都在一个作用域下时,防止不同文件内变量名冲突。它会把每个文件变成独立作用域。可以不加,看自己情况
export {} 

// 1.布尔值
var bols:boolean=true;
bols=false;
// bols=123;(这样写另一种类型就会报错)

// 2.数值型
var num:number=123;
console.log('num==>'+num);

// 3.字符串
var str:string='我是字符串';
console.log('str==>'+str);

// 4.数组   三种方式,常用的是第一种和第三种
var arr1:number[]=[12,34,65];
var arr2:Array<number>=[98,49];
let arr3:any[]=[123,'dsadsad',true];

// 5.元组   属于数组类型的一种,定义每一个位置的类型,会固定数组长度
var tuple:[number,string]=[123,'this is me'];

// 6. 枚举  默认情况下,从0开始为元素编号。 你也可以手动的指定成员的数值
enum flag1 {green=1,red='dfdsfs',pink=8}
let f:flag1=flag1.red;
console.log('f==>'+f)
// 在默认情况下,所代表的值为下标
enum flag2 {green=1,red,pink}
let g:flag2=flag2.red;
console.log('g==>'+g)
/*
如果在使用过程中不会使用到 flag3[1] ,则建议写成const enum flag3 {green,red,pink},
因为这种写法在ts编译时会去除枚举的代码,变成一常量。而不加const的话,编译时不会去除枚举的代码
*/ 
const enum flag3 {green,red,pink}
console.log('flag3', flag3.green)

// 7.任意类型 any
let an:any=123;
let anarr:any[]=[123,'dsadsad',true];
console.log('anarr==>'+anarr[1],'an==>'+an);
// 用法一
var oBtn:any=document.getElementById('btn');
oBtn.style.color="red";

// 8. null和undefined
// 因为u没有赋值,所以它是undefined,但是它类型写的是number,所以编译时会报错
//  var u:number;
//  console.log(u);

var u:number | undefined;
console.log(u);

// 9. void类型   它表示没有任何类型。 当一个函数没有返回值时,你通常会见到其返回值类型是 void
// 一般用于定义没有返回值的方法

// 没有返回值
function fn1():void{
  console.log('fn1');
}
fn1();
// 有返回值
function fn2():number{
  return 123;
}
fn2();

// 10. never类型     表示的是那些永不存在的值的类型。 
//例如, never类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型

函数

expoet {}

// 没有返回值
function fn1():void{
  console.log('fn1');
}
fn1();
var nfn1=function():void{
  console.log('nfn1');
}
nfn1();
// 有返回值
function fn2():number{
  return 123;
}
fn2();
var nfn2=function():number{
  return 123;
}
console.log( nfn2() );

// 函数传参
var argum=function(name:string,age:number):void{
  console.log('我的名字是'+name+',年龄是'+age+'岁');
}
argum('狄仁杰',56);

// 2.函数的可选参数  在参数后面加个'?' (age?:number)  注意:可选参数必须放最后面
var argum1=function(name:string,age?:number):void{
  console.log('我的名字是'+name);
}
argum1('狄仁杰');

// 3.函数的默认参数  注意:默认参数必须放最后面或者也要传值过去(二选一)
var argum2=function(name:string,age:number=18,color:string):void{
  console.log('我的名字是'+name+',年龄是'+age+'岁'+',颜色是'+color);
}
argum2('狄仁杰',5,'red');

// 书写完整函数类型
var argum3 : (a:number, b:number) => number = function(x:number, y:number):number {
  return x + y
}
console.log(argum3(100, 100))

// 4.函数的剩余参数  利用 ES6的扩展运算符...
function buildName(firstName: string, ...restOfName: any[]) {
  return firstName + " " + restOfName.join(" ");
}

let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
console.log(employeeName);

// 5.函数重载
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): any {
    if (typeof x == "object") {
        let pickedCard = Math.floor(Math.random() * x.length);
        return pickedCard;
    }
    else if (typeof x == "number") {
        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 pickedCard1 = myDeck[pickCard(myDeck)];
console.log("card: " + pickedCard1.card + " of " + pickedCard1.suit);

let pickedCard2 = pickCard(15);
console.log("card: " + pickedCard2.card + " of " + pickedCard2.suit);

接口

expoet {}

// 接口(interface)  定义一个规则

interface fullName{//接口是以;结束,加?代表可选参数
  firstName:string;
  lastName:string;
  age?:number;
}

function getName(obj:fullName){
  if (obj.age) {
    console.log('我的名字是:'+obj.lastName+obj.firstName+',我的年龄是:'+obj.age+'岁')
  } else {
    console.log('我的名字是:'+obj.lastName+obj.firstName)
  }
}

// 最好是先定义一个对象,再把对象传入函数,如果直接在函数里写的话必须完全匹配接口规则
let nameObj1={
  firstName:'辉',
  lastName:'赖',
  age:28
}
let nameObj2={
  firstName:'忠',
  lastName:'黄'
}
getName(nameObj1)
getName(nameObj2)
// 下面这样写就会报错,因为是完全匹配,接口里没有定义label这个字段
// getName({
//   firstName:'辉',
//   lastName:'赖',
//   label:'fff'
// })


// 接口的只读属性,赋值之后不可再修改
interface point{
  readonly x:number;
  readonly y:number;
}

let po:point={x:10,y:8};
// po.x=2;//报错


// 接口的函数类型
interface searceFun{//括号里的表示要传的参数,传的时候名字可以不对应,但是数据类型必须一样,冒号后面的是函数的返回值
  (name:string,age:number):string
}

let search:searceFun=function(str:string,num:number):string{
  return `桥的名字是:${str},至今已有${num}年`
}
console.log(search('武汉长江大桥',20))

// 接口的类类型  在给类使用时,是通过implements使用的
interface currentTime{
  currentTime:Date;
}
interface setTime {
  setTime(d:Date):void;
}
interface Eat {
  eat(food: string):void
}

class Food implements Eat {
  constructor() {}
  eat(f:string) {
    console.log(`吃了${f}`)
  }
}

class Clock implements currentTime, setTime{ // 使用多个接口用“,”分割
  currentTime:Date;

  constructor(date:Date){
    this.currentTime=date;
  }

  setTime(date:Date){
    this.currentTime=date;
    console.log(this.currentTime.toLocaleString())
  }
}

let clock=new Clock(new Date());
console.log(clock.currentTime.toLocaleString())
clock.setTime(new Date('2018/6/12 20:15:39'))

泛型

// 泛型是用来传入什么类型就返回什么类型的场景使用
// indeity<T>(name:T):T 这里的T就代表某种类型,可以随意使用26个大写字母来表示,只不过常用的就是T

expoet {}

function indeity<T>(name:T):T{
  return name
}
console.log(indeity<string>('小黄'))// 前面可以传入变量类型    不常用
console.log(indeity('小黄'))// 由编译器来推论    常用

// 指定泛型为一个数组
function loggingIdentity<T>(arg: T[]): T[] {
  console.log(arg.length);  
  return arg;
}
console.log(loggingIdentity([123]))


// 泛型类型
function identity<T>(arg: T): T {
  return arg;
}

let myIdentity: <T>(arg: T) => T = identity;
let myIdentity2: {<T>(arg:T):T} = identity;

console.log(myIdentity(123))
console.log(myIdentity2('理化'))
console.log(identity(456))

// 泛型接口
interface GenericIdentityFn2 {
  <U>(arg:U):U
}
function identity2<T>(arg:T):T{
  return arg
}

let oj:GenericIdentityFn2=identity2;
console.log(oj('见覅啥的回复'))
// 另一种写法
interface GenericIdentityFn3<U> {
  (arg:U):U
}
function identity3<T>(arg:T):T{
  return arg
}

let oj2:GenericIdentityFn3<string>=identity2;
console.log(oj2('sdfg '))

// 泛型类
class GenericNumber<T> {
  zeroValue: T;
  constructor(zeroValue:T){
    this.zeroValue=zeroValue;
  }
  add(){
    console.log(this.zeroValue)
  }
}

let myGenericNumber = new GenericNumber<number>(123);
myGenericNumber.add()

class Person{
  name:string;
  age?:number;
  constructor(name:string,age?:number){
    this.name=name;
    this.age=age;
  }

  getName():void{
    console.log(this.name)
  }

  setName(name:string):void{
    this.name=name;
  }

  getAge():any{
    if(this.age){
      return this.age
    }
  }
}

let p=new Person('赖辉')
p.getName()

p.setName('武则天')

p.getName()

class Web extends Person {
  constructor(name:string,age?:number){
    super(name,age);
  }
  getString(){
    console.log(super.getAge())
  }
  
  getName(){
    console.log('这是子类的')
  }
}

let w=new Web('黄忠',65);
w.getName()
w.getString()

类的三种修饰符

/*
类中定义变量的三种修饰符

public(默认)   公有的            可以在自己本身,子类,和类的外部访问
protected      受保护的          可以在自己本身,子类访问,不能在外部访问
private        私有的            可以在自己本身访问,不能在子类和外部访问
readonly       只读              不能被二次修改赋值

这里所指的不能访问都是指在ts语法中会报错,而经过编译成js之后,还是可以获得结果的,但是还是要按照ts的规则来写

*/

// public

class pubilcOne {
  public game:string;
  constructor(game:string){
      this.game=game+'lol';
  }

  runGame():void{
      console.log('公有变量自己本身类里的:'+this.game);
  }
}

let one=new pubilcOne('绝地求生');
one.runGame()
one.game = '光遇'
console.log('公有定义的变量从外部访问:'+one.game)
one.runGame()


class publicTwo extends pubilcOne{
  constructor(game:string){
      super(game)
  }

  sonGame():void{
      console.log('公有变量子类获取父类的:'+this.game);
  }
}

let two=new publicTwo('王者荣耀');
two.sonGame();
two.runGame();

console.log('==================================================')

// protected

class protectedOne {
  protected game:string;
  constructor(game:string){
      this.game=game;
  }

  runGame():void{
      console.log('受保护的变量自己本身类里的:'+this.game);
  }
}

let three=new protectedOne('武则天');
// console.log(three.game)   //这里访问不了,会报错
three.runGame();

class protectedTwo extends protectedOne{
  protected age?:number;
  constructor(name:string,age?:number){
      super(name);
      this.age=age;
  }

  jiehsao():void{
      if (this.age) {
          console.log('受保护的变量子类获取父类里的:我的名字是'+this.game+',我的年龄是'+this.age+'岁')
      } else {
          console.log('受保护的变量子类获取父类里的:我的名字是'+this.game)
      }
      
  }
}

let four=new protectedTwo('狄仁杰', 18);
four.jiehsao();


console.log('==================================================')

// private

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

  runGame():void{
      console.log('私有的变量自己本身类里的:'+this.name);
  }
}

let five= new privatedOne('小猪佩奇')
// console.log(five.name)    这里访问不了,会报错
five.runGame();

class privatedTwo extends privatedOne{
  constructor(name:string){
      super(name)
  }

  getName():void{
      // console.log('私有的变量子类获取父类里的:'+this.name);      //这里访问不了,会报错
  }
}

let six= new privatedTwo('小猪佩奇');
six.getName();

console.log('==================================================')

// readonly

class readonlyOne{
  readonly name:string;
  constructor(name:string){
      this.name=name;
  }
}

let seven = new readonlyOne('黄忠');
// seven.name='电放费'  这里修改不了,会报错
console.log(seven.name)

类的静态属性和存取器

// static     静态属性     不需要new之后再调用

class Persons{
  static hisname:string='黄忠';
  age:number;

  constructor(age:number){
      this.age=age;
  }

  getAge():void{
      console.log(Persons.hisname+'的年龄是:'+this.age)
  }

  static getName():void{
      console.log('历史人物的名字是:'+Persons.hisname)
  }
}

let eight= new Persons(56);
console.log(Persons.hisname)
Persons.getName()
eight.getAge();

// 存取器   用于变量在类外部的时候更改变量的值

// 不用存取器,直接修改

/*
class Employee{
  fullName:string;
  constructor(name:string){
      this.fullName=name;
  }
}

let employ=new Employee('辉');
console.log(employ.fullName)
employ.fullName='少';//这样虽然可以直接修改,但是可能会带来麻烦
console.log(employ.fullName)

*/

// 存取器修改变量   通过get和set方法去存取变量,如果只写get会被默认设置为readonly只读
class Employee{
  private _fullName:string;
  constructor(name:string){
      this._fullName=name;
  }
  get fullName():string{
      return this._fullName;
  }

  set fullName(newName:string){
      this._fullName=newName;
  }

  eat(){
      // 在自己类里面,fullName和_fullName都可以使用,都代表相同的变量,在其他类或外部只能使用fullName
      console.log(this.fullName+'在吃东西')
      console.log(this._fullName+'在吃东西')
  }
}

class Look extends Employee{
  constructor(name:string){
      super(name)
  }
  eat(){
      // console.log(this._fullName+'在吃东西')   报错
      console.log(this.fullName+'在吃东西')
  }
}

let employ=new Employee('辉');
console.log(employ.fullName)
employ.fullName='少';
console.log(employ.fullName)
employ.eat()

let look=new Look('雪');
look.eat()