什么是TypeScipt?

参考文档官方文档

  1. TypeScript 是由微软开发的一款开源的编程语言。
  2. TypeScript 是 Javascript 的超集,遵循最新的ES6、Es5 规范。TypeScript 扩展了 JavaScript 的语法。
  3. TypeScript 更像后端java、C#这样的面向对象语言,可以让 js 开发大型企业项目。
  4. 谷歌也在大力支持 Typescript 的推广,谷歌的angular2.x+就是基于 Typescript 语法。
  5. 最新的 Vue 、React 也可以集成 TypeScript。Nodejs 框架 Nestjs、midway 中用的就是 TypeScript 语法。
  6. 带有类型,是说js在定义变量的时候,类型是动态的,只有在运行的时候才能知道它的具体类型,比如 number或者string,并且类型也是可以动态变化的,而TypeScript则是要求变量有确定的类型,并且在编写代码的时候就已经确定,如果把字符串赋给类型为 number,数字类型的变量,就会出错。

TypeScript安装、编译

安装

npm install -g typescript 
或者cnpm install -g typescript 
或者yarn global add typescript

运行

tsc helloworld.ts

数据类型

数据类型有两种,分为隐性与显性。

隐性

隐式类型是由 TypeScript 根据变量的值来推断类型,这样的话,代码的写法跟 JS 就一样了,但不同的是它后边不能用其他类型的值来给他重新赋值。

let a = 10;
a = 'hello'; // 自动推断为string类型
显性
var flag: boolean = true;
 flag = false;
声明类型的几种语法
/* 第一种写法 *//

var arr: number[] = [1, 2, 3, 4]
console.log(arr);

//* 第二种写法 *//

var arr1: Array<any> = ['20', 4596, true, { a: 1 }]
console.log(arr1);

//* 第三种写法 *//

var arr2: any[] = ['20', 4596, true, { a: 1 }]
console.log(arr2);
元组类型tuple
var arr3: [number, string, boolean] = [123, 'aa', false]
console.log(arr3);
枚举类型(enum)
enum Status { success = 2000, error = 5000 };
var s: Status = Status.success;

console.log(s);

enum Color { blue, red, green }

let c: Color = Color.red;

console.log(c);// 1 如果标识符没有赋值 他的值就是他的下标

枚举例子

// 默认情况下,从0开始为元素编号。 你也可以手动的指定成员的数值。
enum Animals { Duck = 1, Monkey, Donkey }
let animal: Animals = Animals.Donkey
console.log('animal', animal);

// 如果我们知道数值是2,但是不确定他映射到Animals里的那个名字,可以这样查找

let animasName: string = Animals[2]
console.log('animasName', animasName); // Monkey

如果给定第一个属性的值为一个常量,其后面的属性值为自增趋势

enum Direction {
    Up = 1,
    Down,
    Left,
    Right,
}
// 上面的例子 Up = 1 那Down = 2 ...

enum Direction {
    Up,
    Down,
    Left,
    Right,
}
// 上面的例子 Up 没有被指定 那默认为0

访问枚举中的属性

enum Dd {
    No,
    Yes = 1,
    Status,
}

console.log(Dd['Yes']);// 1
console.log(Dd['No']);// 0
console.log(Dd['Status']);// 2

例子

enum E {
    X, Y, Z
}
function f(obj: { X: number }) {
    return obj.X;
}

// Works, since 'E' has a property named 'X' which is a number.
console.log(f(E));

 enum Enum {
    A = 1,
    B,
    C = 2
}
console.log(Enum['B']);// 2
任意类型(any)
var num: any = 123;
num = 'str'
num = true;
console.log(num);
对象类型 object
var obj: object = ['11', 33, 'sdsd']
console.log(obj);
nerver 类型

其他(never类型)数据类型的子类型

var a: never;
console.log(a, 'a');

//返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
    while (true) { }
}
void类型

typescript中的void表示没有任何类型,一般用于定义方法的时候方法没有返回值。

function run(): void {
    console.log('run');
}
run()

function run1(): void {
    return 1245 // 报错 定义方法的时候方法没有返回值
}
run1()
组合类型
var num1: number | undefined;
console.log(num ? true : false) // 返回true
console.log(typeof num);

// 组合类型也可以直接使用字面值来定义,这样就规定了一个变量的取值范围
let g: "on" | "off" = "on"
g = "off"
类型别名 type

// 这样代码看起来不太方便,并且这个组合类型只能给 a 使用,如果有一个变量 b 也可以同时是 number 或 string 的类型的话,还要重复定义这个类型。要解决这个问题,我们可以使用 type 关键字来给这个组合类型起个别名,让代码更易读,也方便其他变量使用,这里定义一个 type 名字叫 NumStr,自定义的类型名字推荐首字母大写.

type NumStr = string | number // 给类型组合定义一个别名 (type关键字)

let bb: NumStr = '456456'
console.log(bb, 'bb');
函数 function
// 1 有返回值

function dev(): string {
    return '12435' // 正确写法
    // return true // 报错
}
dev()

// 2 无返回值

function dev1(): void {
    console.log('函数没有返回值');
}
dev1()

// 3 箭头函数 
const materials = ['1', '2', '3', '4']

console.log(materials.map((material): any => console.log(materials.length, 'materials.length')))

// 4 定义方法中的传参

function animals(name: string, age: number): string {
    return `${name}---${age}`
}
console.log(animals('吉吉国王', 5))
函数重载

函数重载其实就是: 多个函数函数名相同,函数的参数类型,顺序,个数不同。注意函数重载与返回值类型无关。
ts的函数重载比较鸡肋,最终函数逻辑的实现还是在一个函数体内去判断它的参数类型,然后做相应的操作。ts
重载的作用,感觉只是多了一个参数校验的功能。也就是说在进行函数调用的时候,会对参数进行检查,只有传
入的参数类型,顺序,个数与定义的重载函数的参数相同,才能调用成功,否则报错。返回值类型不会进行校验
(函数重载与返回值类型无关)。

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 {
    // Check to see if we're working with an object/array
    // if so, they gave us the deck and we'll pick the card
    if (typeof x == "object") {
        let pickedCard = Math.floor(Math.random() * x.length);
        // return pickedCard;
        return 'pickedCard'; // 并不会报错,编译是通过的
    }
    // Otherwise just let them pick the card
    else if (typeof x == "number") {
        let pickedSuit = Math.floor(x / 13);
        return { suit: suits[pickedSuit], card: x % 13 };
    }
}
接口 interface

用来描述对象的内部类型结构

interface Person {
    name: string,
    age: number,
    marry: boolean
}

function getPerson(person: Person): string {
    return `hello,m我的名字叫${person.name},今年${person.age}岁了,婚姻状态是${person.marry ? '已婚' : '未婚'}`
}

let result = getPerson({
    name: '李磊', age: 18, marry: false
})
console.log(result);

2.接口的继承
interface Animal {
    run: boolean;
}

interface Dog extends Animal {
    eat: boolean;
}

interface Bird extends Animal {
    fly: boolean;
}

let animl = <Dog>{};
animl.run = true
animl.eat = true
console.log(animl);
类 class
class Person {
    private ball: string; // 私人有 只能内部访问
    protected money: number; // 受保护,只能内部访问
    static information: string; // static 不被实例化的属性感觉和private差不多
    information: string; //
    constructor(public name: string, public age: number, public marry: boolean) {
        this.information = `hello,我的名字叫${name},今年${age}岁了,婚姻状态是${marry ? '已婚' : '未婚'}`
    }
}

// 实现一个存取器

class Gather {
    private _gatherName: string
    protected password: number

    get gatherName(): string {
        return this._gatherName
    }

    set gatherName(newName: string) {
        this._gatherName = newName;
    }
}

let oo = new Gather()

console.log(oo);
oo.gatherName = '王五'
console.log(oo);
只读 readonly
let array: number[] = [1, 8, 8, 4, 8]
// ReadonlyArray 指定只读状态,指定之后不可再做修改,否则报错
let role: ReadonlyArray<number> = array
role[0] = 45645 // 报错

//如果想修改内部属性,可以用类型断言重写此变量
array = role as number[];
类类型

个人见解:类类型就是对类class 做了一个约定,也可以叫做约束,体现在入参的类型上。

类类型分为两个部分 1.静态部分 2.实例部分。

interface clockConstructor {
    new(hour: number, minute: number);
}
class Clock implements clockConstructor {
    currentTime: Date;
    constructor(h: number, m: number) { }
}
// 以上这种方式去实现,会出现报错
// 类“Clock”错误实现接口“clockConstructor”。
//   类型“Clock”提供的内容与签名“new (hour: number, minute: number): any”不匹配。ts(2420)

正确写法

interface ClockConstructor {
    new(hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
    tick();
}

function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {
    return new ctor(hour, minute);
}

class DigitalClock implements ClockInterface {
    constructor(h: number, m: number) {
        console.log('DigitalClock', h, m);
    }
    tick() {
        console.log("beep beep");
    }
}
class AnalogClock implements ClockInterface {
    constructor(h: number, m: number) {
        console.log('AnalogClock', h, m);
    }
    tick() {
        console.log("tick tock");
    }
}

let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 7, 32);
digital.tick()
analog.tick()
混合类型
interface Counter {
    (start: number): string;
    interval: number;
    start: number;
    reset(): void;
}

function getCounter(): Counter {
    let counter = <Counter>function (start: number) {
        this.start = start
        console.log(this.start, 15674532156);
    };
    counter.interval = 123;
    counter.start = 0;
    counter.reset = function () {
        console.log(this);
        console.log('数据重置中···');
        this.start = 0
    };
    return counter;
}

let h = getCounter();
h(10);
h.reset();
console.log(h.start, 'h,start');
h.interval = 5.0;
泛类型

个人见解:不设置类型意为泛类型

function fun1<T>(arg: T[]) {
    console.log(arg.length);
}
fun1([1, 2, 4, '2'])

// 在泛型里使用类类型
class BeeKeeper {
    hasMask: boolean;
}

class ZooKeeper {
    nametag: string;
}

class Animal {
    numLegs: number;
}

class Bee extends Animal {
    keeper: BeeKeeper;
}

class Lion extends Animal {
    keeper: ZooKeeper;
}

function createInstance<A extends Animal>(c: new () => A): A {
    return new c();
}

// let A = createInstance(Lion).keeper.nametag;  // 报错
let A = createInstance(Lion).keeper;  // undefined
// let B = createInstance(Bee).keeper.hasMask;   // 报错
let B = createInstance(Bee).keeper;   // undefined
console.log(A,'A');
console.log(B,'B');

End~

未完待续…