TypeScript学习笔记

//typeScript数据类型
//ts有类型推导,你可以不必写后面的类型,ts会在第一次赋值时自动推导出数值的类型
//布尔类型(blooean)
let flag: boolean = true;
// 简写成let flag = true //会自动推导出事blooean类型
flag = false;
//数字类型(number).这里整数和浮点数统称为number类型
let a: number = 123;
a = 456;
a = 1.223;
console.log(a);
//字符串类型(string)
let str: string = "你好啊";
str = "哈哈哈";
//数组类型(array)
//es5的数组可以随便定义,不能我们一般不这么使用 var arr = [1, "你好", true]
//es6
//第一种定义方式
let arr: number[] = [1, 2, 3];
//第二种(运用泛型)
let arr1: Array<number> = [4, 5, 6];

//元组类型(tuple) 相当于属于数组的一种,只是每一项可以定义类型
let yuanzu: [number, string, boolean] = [1, "呵呵呵", false];

//枚举类型(enum)

enum Status {
  suncces_t = 200,
  err_t = 404,
}
var q_status: Status = Status.err_t;
console.log(q_status);

//如果枚举变量不设定初始值,默认的是从0开始的数字索引值
enum Color {
  red,
  blue,
  orange,
}
console.log(Color.red); //输出结果是0
console.log(Color.blue); //输出结果是1
console.log(Color.orange); //输出结果是2

enum Color1 {
  red,
  blue = 10,
  orange,
}
console.log(Color1.red); //输出结果是0
console.log(Color1.blue); //输出结果是10
console.log(Color1.orange); //输出结果是11

//任意类型(any)

let num: number = 12;
// num = "你好"  如果这样赋值的话会报错,因为typescript是严格数据类型,类型不一样会报错
let num1: any = false;
num1 = "jjj"; //随便赋值不会报错,任意类型的值都可以
num1 = null;
console.log(num1);
//-----任意类型的用法
//如下常在js写的代码 在js中不会报错  但在ts中会报错  var box = document.getElementById("box") box.style.color="red"

//在ts中应该这么写
// var box: any = document.getElementById("box");
// box.style.color = "red";

//null和undfiend (是其他(never类型)数据类型的子类型)
// var b:number  console.log(b) //输出undefined 报错
//正确写法
var b: undefined;
console.log(b);
//联合类型
var c: number | undefined; //管道符可以给定义多个类型 满足其中一个就行
console.log(c);
c = 100;
console.log(c);

//定义为null,值只能为null
var d: null;
d = null;

var e: string | null | undefined;
e = null;
e = undefined;
e = "饿了么";
console.log(e);

//void类型:表示没有任何类型,一般用于定义方法时的没有返回值
//es5定义方法
function run() {
  console.log("跑步");
}

//在ts中定义没有返回值的方法
//定义方式 function(形参1:参数类型,形参2:参数类型):返回值类型 {}

//void表示方法没有返回任何值(注意没有返回值和返回null和undifend不同,null和undefined也是数据类型)
function swim(): void {
  console.log("我会游泳");
}
function goschool(name: string, age: number): string {
  return `我是${name},今年${age}岁`;
}
let dec = goschool("小敏", 5);
console.log(dec);

//never类型:完全无返回值的类型,只有一种情况会如此:代码阻断
//这意味着当执行throw new Error, return process.exit(1),while(true){}这些代码时满足条件
//如果函数的返回值类型是 never 意味的此函数必须不能被顺利完整执行,而发生中断行为

var n: never;
//所有类型的子类型
function fun(s: string): number {
  if (s == "a") return 1;
  if (s == "b") return 2;
  throw new Error();
}
// 等同于 fun(s: string): number | never

// 函数定义
//    function 函数名(形参1:参数类型,形参2:参数类型):返回值类型 {}
//匿名函数
var func = function () {};
//方法的可选参数:在es5里面的方法的实参和形参可以不一样,但在ts中必须一样,如果不一样就需要配置可选参数
// function 方法名(必传形参: 形参类型,可选形参?:形参类型):返回值{}
//注意可选参数必须配置到参数的最后面
function eat(name: string, age?: number): string {
  if (age) {
    return `我是${name},今年${age}岁,我爱吃饭`;
  } else {
    return `我是${name},我爱吃饭`;
  }
}
console.log(eat("小明"));
console.log(eat("小明", 20));
//函数默认参数
//在es5中没法设置默认参数,在es6和ts中都可以设置默认参数
function eat1(name: string, age: number = 20): string {
  return `我是${name},今年${age}岁,我爱吃饭`;
}
//剩余参数:
function sum(a: number, b: number, ...reslult: number[]): number {
  let sum = a + b;
  for (let i = 0; i < reslult.length; i++) {
    sum += reslult[i];
  }
  return sum;
}
console.log(sum(1, 2, 3, 4, 5)); //会把1赋值给a,2赋值给b,剩余的放到剩余参数的数组中

//函数重载
//函数名相同,参数类型不同
/*
此功能真鸡肋,ts重载的作用,感觉只是多了一个参数校验的功能。
也就是说在进行函数调用的时候,会对参数进行检查,只有传入的参数类型,顺序,个数与定义的重载函数的参数相同,才能调用成功,否则报错。
返回值类型不会进行校验(函数重载与返回值类型无关)
*/
function getInfo(num1: string,num2: string): string;
function getInfo(num1: number,num2:number): number;
function getInfo(a: any, b:any): any {
 return  a+ b
/如果比较复杂时可以先判断类型再进行操作
 //if(typeof a === 'string' && typeof b === 'string'){...return...}else{...return..}
}
getInfo(3,5) //输出8.会自动匹配function getInfo(num1: number,num2:number): number这个函数

getInfo("你好","世界") //输出你好世界, 会自动匹配getInfo(num1: string,num2: string): string;

注意:在函数重载中,实现函数是不能直接被调用的,如果上面定义的函数都没匹配到,那就会报错

//类
class Person {
  name: string; //省略了前面public关键词
  age: number;
  // 构造函数,实例化类的时候会触发
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
  run() {
    console.log("我是" + this.name + "," + "我在运动");
  }
  //也可以写setter和getter方法
}
//创建实例化对象
let p = new Person("张三", 18);
console.log(p.age);
p.run();
p.name = "小工";
p.run();

//ts中的继承 extends super
class Man extends Person {
  aihao: string;
  constructor(aihao: string, name: string, age: number) {
    super(name, age);
    this.aihao = aihao;
  }
  run() {
    console.log(
      "我是" + this.name + "," + "我的爱好是" + this.aihao + "我在运动"
    );
  }
}

let man = new Man("打游戏", "小k", 18);
man.run();

//类里面的修饰符
//ts定义属性的时候给我们提供了三种修饰符
// public : 公有属性,在类里面 子类 类外面都可以访问
// private: 私有属性  在类里面可以访问 子类 类外部没法访问
// protected: 被保护属性  在类里面 子类里面都可以访问 在类外面没法访问

//类中的静态属性 静态方法
/*
在es5中定义实例方法和静态方法
function Animal(){
  // 实例方法
  this.sleep = function(){
    console.log("我爱睡觉")
  }
}
实例方法调用: let animal = new Animal() animal.sleep()
// 静态方法
Animal.speak = function(){}  
静态属性 Animal.height = 150
静态方法调用Animal.speak()
*/
//在ts中定义静态属性和静态方法
class Car {
  name: string;
  static color: string = "黑色";
  constructor(name: string) {
    this.name = name;
  }
  // 实例方法
  run() {
    console.log("我是会跑的小车车");
  }
  //静态方法 声明时前面加上static,在静态方法里面没法调用实例属性,因为这里面的this不是实例对象,而是类对象
  static stop() {
    console.log("我的" + this.color + "车子停止了");
  }
}

let sCar = new Car("小汽车");
sCar.run(); //实例方法调用
Car.stop(); //静态方法调用

// 多态 : 父类定义一个方法不去实现,让继承它的子类去实现,每个子类有不同的表现

class Obj {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  eat() {
    console.log("我定义了一个方法,但我没有具体去实现");
  }
}

class Obj1 extends Obj {
  constructor(name: string) {
    super(name);
  }
  eat() {
    return "我是Obj1,这是我实现的方法";
  }
}

class Obj2 extends Obj {
  constructor(name: string) {
    super(name);
  }
  eat() {
    //函数的返回值可以生了不写,会自动推断
    return "我是Obj2,这是我实现的方法";
  }
}

// 抽象方法
//在ts中的抽象类:他提供其他类继承的基类,不能直接被实例化
//用abstract关键字定义抽象类,抽象类中的抽象方法不包含具体的实现并且必须在派生类中实现
//abstract抽象方法只能放在抽象类里面
//抽象类和抽象方法用来定义标准

//定义一个车类.要求车子必须会跑
abstract class Cars {
  //抽象类面可以有非抽象方法,但必须至少包含一个抽象方法
  //父类只定义抽象方法 不实现 等子类实现
  abstract run(): void;
  //抽象类也可以有非抽象方法 子类可以不用实现
  stop() {
    console.log("我的车子刹不住");
  }
}

//错误的写法  let cars = new Cars()  抽象类无法被实例化
//继承用extends
class BigCar extends Cars {
  //抽象类的子类必须要实现抽象方法
  run() {
    console.log("我是一个会跑的车子,我符合标准,我实现了父类的抽象方法");
  }
}

let bigCar = new BigCar();
bigCar.run();
bigCar.stop;

//接口interface

//单个的约束
//{ name: string }就是对传入数据的约束
function printInfo(info: { name: string }) {
  console.log("我的名字是=" + info.name);
}
printInfo({ name: "张三" });
//printInfo({ dec: "张三" }); 错误的写法

//如果对很多传入的数据都进行约束 如果按上面的写法会非常麻烦 这时候我们就用到了接口 interface

//属性接口
//如果传入一个对象,参数必须是字符串,且包含firstName和secondName
//定义接口
interface FullName {
  firstName: string;
  secondName: string;
}

function getPersonalName(name: FullName) {
  console.log(name.firstName + name.secondName);
}
getPersonalName({ firstName: "张", secondName: "三" });

//可选属性接口
/*
interface 接口名称 {
  接口形参:形参类型;
  接口形式1?:形参类型; //可选属性接口,这个值可传可不传
}
*/

//函数类型接口:主要对函数的参数个数 参数类型和返回值类型的约束
interface funcType {
  (a: string, b: string): string;
}

let funs: funcType = function (name: string, address: string): string {
  return "我的名字=" + name + "," + "我住在" + address;
};
console.log(funs("小李", "玉龙山庄"));

//可索引接口:对数组.对象的约束(不常用)

//对数组的约束
interface customArr {
  // 索引值是number 值为string的接口
  [index: number]: string;
}
let arr2: customArr = ["周一", "周二"];
console.log(arr2);

//对对象约束
interface customObj {
  [index: string]: string;
}
let dic: customObj = { name: "hhh", dec: "jj" };
console.log(dic);

//类类型接口:对类进行约束
//定义类面含有的属性,方法等
interface CustomP {
  name: string;
  speak(word: string): string;
}

class xiaoP implements CustomP {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  speak(a: string) {
    return "我的名字叫" + this.name + "我说了句" + a;
  }
}

let xiaop = new xiaoP("小p");
console.log(xiaop.speak("我好大"));

//接口的扩展:接口可以继承接口
//接口继承接口时子接口类除了实现自身约束的内容外还要实现父接口里面的所内容
interface SmallP extends CustomP {
  age: number;
  dnner(): void;
}
class SP implements SmallP {
  name: string;
  age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
  speak(a: string) {
    return "我的名字叫" + this.name + "我今年" + this.age + "岁,我说了句" + a;
  }
  dnner() {
    console.log("我是一个新方法");
  }
}

let sp = new SP("小红", 18);
console.log(sp.speak("我是老sp"));
sp.dnner();

//继承类且实现接口
//首先需要考虑接口里面的约束要全部实现,同时要考虑要父类有属性时要调用父类初始化器
class PP {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  dothings(dec: string) {
    console.log("我爱-->" + dec);
  }
}
class ZPP extends PP implements CustomP {
  constructor(name: string) {
    super(name);
  }
  speak(w: string) {
    return "我是zpp" + "我说了句" + w;
  }
}

let zpp = new ZPP("我是小zpp");
console.log(zpp.speak("真丑"));
zpp.dothings("做爱做的事");

//泛型:解决复用性,以及数据类型的多样性

function oneandoneadd<T>(a: T): T {
  return a;
}
function oneandoneadd1<T extends string | number>(a: T): T {
  return a;
}
console.log(oneandoneadd<string>("你好"));
console.log(oneandoneadd1(1));

//泛型类

class MinClass<T> {
  list: T[] = [];
  add(value: T) {
    this.list.push(value);
  }
  min(): T {
    let min = this.list[0];
    for (let i = 0; i < this.list.length; i++) {
      if (min > this.list[i]) {
        min = this.list[i];
      }
    }
    return min;
  }
}
let m = new MinClass<number>();
m.add(25);
m.add(77);
m.add(10);
console.log(m.min()); //输出结果10

let m1 = new MinClass<string>();
m1.add("张");
m1.add("王");
m1.add("赵");
console.log(m1.min()); //输出结果张

//泛型接口
interface CConfig<T> {
  plus(a: T, b: T): T;
}

class Con implements CConfig<string> {
  plus(a: string, b: string) {
    return a + "----" + b;
  }
}
let con = new Con();
console.log(con.plus("hello", "world"));

class Non implements CConfig<number> {
  plus(a: number, b: number) {
    return a + b;
  }
}
let non = new Non();
console.log(non.plus(1, 5));

//命名空间 namespace ***  避免命名冲突
//要注意和模块区分
namespace A {
  //默认里面的内容是私有的,想在外面使用,用export进行暴漏
  export function srun() {
    console.log("跑起来");
  }
  function curn() {
    console.log("在外部无法调用");
  }
}
//调用
A.srun();
// A.curn() //报错
namespace B {}

//装饰器:装饰器就是一个方法,可以注入到类 方法 属性参数来扩展类 属性  方法 参数的功能
//类装饰器:类装饰器在类声明之前被声明(紧靠着类声明).类装饰器应用于构造函数,可用来监视,修改或替换类定义

//创建一个类装饰器
function classdec(params: any) {
  console.log(params); //打印出来的params其实就是被装饰的类本身,然后拿着这个类在原型链上可以新增一些属性和方法
  params.prototype.api = "bbbbb"; //在原型链上扩展属性
  params.prototype.requset = function () {
    console.log("我是扩展的方法");
  };
}

//用@装饰器名字  紧挨着类的声明  装饰器后面不要写分号
@classdec //普通装饰器
//定义一个类
class HttpNet {
  constructor() {}
  getData() {}
}

let net: any = new HttpNet();
console.log(net.api); //打印出bbbbb
net.requset(); //输出我是扩展的方法

//带参数装饰器,装饰器工厂
function leidec(para: string) {
  return function (target: any) {
    console.log(target);
    console.log(para);
    target.prototype.api = para; //在原型链上扩展属性
    target.prototype.requset = function () {
      console.log("我是扩展的方法");
    };
  };
}

@leidec("http://www.nnnn") //net赋值给了para  当前的类赋值给了target
class NetWork {
  run() {}
}

//类装饰器重载构造函数

function classReload(target: any) {
  return class extends target {
    kk: string = "366666";
    getData() {
      this.atr = this.kk;
      console.log(this.atr);
    }
  };
}

@classReload
class MineClass {
  atr: string | undefined;
  constructor() {
    this.atr = "我是梦";
  }
  getData() {
    console.log("我是方法---",this.atr);
  }
}

//属性装饰器
function  classAttr(params:string){
  return function(target:any,attr:any){
    console.log(target) //target当前类的原型对象,
    console.log(attr) //当前属性 name
    target[attr] = "" //可以修改类中的属性值
  }
}

class MClass {
  //装饰url属性
  @classAttr("kkkkkk")
  name:any | undefined
  constructor(){

  }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,270评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,489评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,630评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,906评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,928评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,718评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,442评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,345评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,802评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,984评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,117评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,810评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,462评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,011评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,139评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,377评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,060评论 2 355