### 1. typescript 介绍
typeScript是javascript的一个超集, 它遵循最新的es6脚本语言规范,ts扩展了js语法, 已经存在的js程序可以不经过任何改动的情况下在ts里运行.

优点
  • 编译时的强类型: ts设计了一套类型机制来保证编译时的强类型判断.例如你可以声明变量的类型, 那么任何其他类型的赋值将会引起编译错误
  • 模块化: 利用ts的关键词module,可以达到命名空间的效果.而export可以控制是否被外部访问
module Project {
    export module Core {
        function FunA(){};
        export function FunB() {
            FunA()
        }
    }
}

module Project.Core {
    export function FunC() {
        FunA(); // error
        FunB(); // ok
    }
}


Project.Core.FunA(); // error
Project.Core.FunB(); // OK
Project.Core.FunC(); // OK
  • 语法糖: TypeScript可以实现类,接口,枚举,泛型,方法重载等,用简洁的语法丰富了JavaScript的使用。

环境搭建

mac 环境 node => v10.0.0
全局安装 npm install -g typeScript
命令执行tsc -v 查看版本
使用vscode 配置自动编译
在项目下新建tsconfig.json配置文件
新建app.ts
在命令行中执行 tsc app.js
选择运行任务
image.png
选择tsconfig.json监视

基础

原始数据类型

javascript的类型分为两种: 原始数据类型和对象类型
原始数据类型包括: boolean, number, string null undefined以及es6新定义的symbol

boolean

布尔值是最基础的数据类型, 在ts中使用boolean定义布尔值类型:

let isDone: boolean = false;

注意使用构造函数Boolean创造的对象不是布尔值

let createdByNew: Boolean = new Boolean(1)

// var creatednew = new Boolean(1);

在ts中, boolean是js的基本数据类型, 而Boolean是js中的构造函数.

数值number

使用number定义数值类型

let decliter: number = 6;
let binary: number = 0b1010;
let notANumber: number = NaN;
let infinityNumber: number = Infinity;

//编译后 
var decliter = 6;
var binary = 10;
var notANumber = NaN;
var infinityNumber = Infinity;
字符串

使用string定义字符串类型

// 字符串
let myName: string = 'Tom';
let myAge: number = 25;
// 模板字符串
let sentence: string = `hello, my name is name is ${myName}. `
// 编译后
// 字符串
var myName = 'Tom';
var myAge = 25;
// 模板字符串
var sentence = "hello, my name is name is " + myName + ". ";
空值

js中没有空值Void的概念. 在ts中可以用void表示没有任何返回值的函数

function alertName(): void {
    alert('1111')
}

// 编译后

function alertName() {
    alert('1111');
}

声明一个void类型的变量没有什么用,因为只能将它赋值为undefined和null

Null和Undefined

在ts中.可以使用null和undefined来定义这两个原始数据类型

let u: undefined = undefined;
let n: null = null;
// 编译后
var u = undefined;
var n = null;

与void的区别是, undefined和null是所有类型的子类型.也就是说undefined类型的变量.可以赋值给number类型的变量

let num: number = undefined;
let u2: undefined;
let num2: number = u2;
// 编译后
var num = undefined;
var u2;
var num2 = u2;

而void类型的变量不能赋值给number类型的变量

let u3: void;
let num3: number = u3;
// 报错 Type 'void' is not assignable to type 'number'

任意值

任意值Any用来表示允许赋值为任意类型

什么是任意值类型

如果是一个普通类型. 在赋值过程中改变类型是不被允许的

let myFavorite: string = 'seven';
myFavorite = 7;
// 报错 Type 'number' is not assignable to type 'string'.

但如果是any类型. 则允许被赋值为任意类型

let myFavorite: any = 'seven';
myFavorite = 7;
// 编译后
let myFavorite: any = 'seven';
myFavorite = 7;
任意值的属性和方法

在任意值上访问任何属性都是允许的

let anything: any = 'hello';
console.log(anything.myname);
console.log(anything.myName.firstName);
// 编译后
var anything = 'hello';
console.log(anything.myname);
console.log(anything.myName.firstName);

也允许调用任何方法

let anything2: any = 'tom';
anything2.setName('jenny');
// 编译后
var anything2 = 'tom';
anything2.setName('jenny');

可以认为声明一个变量为任意值后,对它的任何操作, 返回的内容的类型都是任意值.

未声明类型的变量

变量如果在声明的时候, 未指定其类型, 那么它会被识别成任意值类型.

let something;
something = 'seven';
something = 7;
// 等价于
var something;
something = 'seven';
something = 7;
弊端

一夜回到解放前. everything is any, ts基本就是js了
检查变量的时候不能快速知道类型

ts中的顶级类型 any和unknown

any和unKnown在ts中是所谓的顶级类型
也就是说如果把类型看作是值的集合时, any和unKnown是所有值的集合

类型推论

如果没有明确的指定类型, 那么ts会依照类型推论的规则推断出一个类型

什么是类型推论

以下代码虽然没有指定类型, 但是他会在编译的时候报错

let myjfjf = 'seven';
myjfjf = 7;

// 报错  Type 'number' is not assignable to type 'string'

事实上,它等价于

let myjfjf: string = 'seven';
myjfjf = 7;

ts 会在没有明确的指定类型的时候推测出一个类型, 这就是类型推论
如果定义的时候没有赋值.不管以后有没有赋值, 都会被推断为any类型而完全不被类型检查

联合类型

联合类型表示取值可以为多种类型中的一种

let jffjjl: string | number;
jffjjl = 'seven';
jffjjl = 7;
// 编译为: 
var jffjjl;
jffjjl = 'seven';
jffjjl = 7;


let ndnnf: string | number;
ndnnf = true;
// 报错  Type 'boolean' is not assignable to type 'string | number'.

联合类型使用|分隔每个类型

访问联合类型的属性或方法

当ts不确定一个联合类型的变量到底是哪个类型的时候, 我们只能访问此联合类型的所有类型里共有的属性或者方法

function getLength(someth: number | string): number {
  return someth.length
}
// 报错: Property 'length' does not exist on type 'string | number'.
  Property 'length' does not exist on type 'number'.

表示length属性不是number和string的共有属性, 所以会报错
访问string和number的共有属性是没问题的

function getLength(someth: number | string): string {
  return someth.toString();
}
// 编译后
function getLength(someth) {
    return someth.toString();
}

联合类型的变量在被赋值的时候, 会根据类型推论的规则推断出一个类型:

let iuruio: string | number;
iuruio = 'seven';
console.log(iuruio.length);
// 编译正常
iuruio = 7;
console.log(iuruio.length);
// 编译报错

上述例子中第二行的iuruio被推断成了string
而第四行iuruio被推断成了number

对象的类型 - 接口

在ts中, 我们使用接口interface来定义对象的类型

什么是接口

在面向对象语言中, 接口interface是一个很重要的概念. 它是对行为的抽象.
ts中的接口除了可用于对类的一部分行为进行抽象以外, 也常用于对对象的形状进行描述

interface Person {
  name: string,
  age: number
}

let tom: Person = {
  name: '张三',
  age: 12
}
// 编译为
var tom = {
    name: '张三',
    age: 12
};

上面例子中, 定义了一个接口Person,接着定义了一个变量tom, tom的类型是Person,这样我们就约束了tom的形状必须和接口Person一致
接口一般首字母大写

定义变量比接口少一些属性是不允许的, 多一些属性也是不允许的

let tom: Person = {
  name: '张三'
}
 Type '{ name: string; }' is not assignable to type 'Person'.
//   Property 'age' is missing in type '{ name: string; }'

let tom: Person = {
  name: '张三',
  age: 12,
  hhh: '33'
}
Type '{ name: string; age: number; hhh: string; }' is not assignable to type 'Person'.
  Object literal may only specify known properties, and 'hhh' does not exist in type 'Person'.

可见赋值的时候, 变量的形状必须和接口保持一致

可选属性

有时候我们希望不要完全匹配一个形状, 可以使用可选属性

interface Person {
  name: string,
  age?: number
}

let tom: Person = {
  name: '张三'
}
// 编译为
var tom = {
    name: '张三'
};
任意属性

希望一个接口有任意的属性, 可以使用[propName]

interface Person {
  name: string,
  age?: number,
  [propName: string]: any
}

let tom: Person = {
  name: '张三',
  age: 11,
  gender: 33,
  eqweL: 33
}
// 编译为
var tom = {
    name: '张三',
    age: 11,
    gender: 33,
    eqweL: 33
};

需要注意的是: 一旦定义了任意属性, 那么确定属性和可选属性的类型都必须是它的类型的子集
一个接口中只能定义一个任意属性, 如果接口中有多个类型的属性.则可以在任意属性中使用联合类型.

interface Person {
  name: string,
  age?: number,
  [propName: string]: string | number
}

let tom: Person = {
  name: '张三',
  age: 11,
  gender: 33,
  eqweL: 33
}
// 编译为: 
var tom = {
    name: '张三',
    age: 11,
    gender: 33,
    eqweL: 33
};
只读属性

希望对象中的一些字段只能在创建时赋值, 可以使用readonly定义只读属性:

interface Person {
  readonly name: string,
  age?: number,
  [propName: string]: string | number
}
let tom: Person = {
  name: '张三',
  age: 11,
  gender: 33,
  eqweL: 33
}
tom.name = '李四';
// 报错 Cannot assign to 'name' because it is a read-only property.

lolo
12 声望0 粉丝