简介
ts是js类型的超集,它可以编译成纯js。
ts可以再任何浏览器、任何计算机和任何操作系统上运行,并且是开源的
拓展
- 类Classes
- 接口interfaces
- 模块Modules
- 类型注解Type annotations
- 编译时类型检查Compile time type checking
- Arrow 函数(类似C#的Lambda表达式)
部署环境
npm install -g typescript
编译ts文件
tsc 文件名
vscode可以自动编译ts文件
将默认终端改成cmd
通过命令初始化tesconfig.json文件
tsc -init
启动监视
终端→运行任务→tsc监视
强大的类型系统
强大的静态分析能力。
我们写js的时候,声明一个变量,只需要写一个let就可以,无论他是字符串还是数字,还是小数,还是方法,还是…
因为ts要求我们,在写一个变量的时候,要去说明这个变量的类型,写一个方法的时候,要去声明方法的类型,写一个对象的时候,要去声明对象的类型,写一个。。。
主要起规范作用。能够减少开发过程中的错误。如果不规范ts经过静态分析会给我们报错。我们能够及时纠正写法。
变量:
变量的类型
string 字符串类型 只能接受字符串
number 数字类型 只能接受数字
boolean 布尔类型 只能接受true或false
null 表示空,没有 只能接受null
undefined 未定义 只能接受undefined
但是null,undefined在非严格模式下,可以被赋值给其他类型
never 意外类型 如果没有合适的类型表达,就是用never意外类型
类型断言
将一个类型的值赋值给另一个类型的变量方法
let s3:number = <number><any>"1";
let s4: number = "1" as any as number;
类型推断
在不指定类型的情况下,ts会根据变量的第一个值的类型来规定自己的类型
let s6 = "jack";//ts推断出s6是字符串类型
数组:
// 为所欲为
let arr = [1,"jack",true];
arr.push("1");
arr.push(23)
// 可以声明数组的类型为字符串
// 字符串类型的数组里面只能装字符串
let arr2:string[]=[];
arr2.push("jack");
arr2.push(123 as any as string);
arr2.push(undefined);
arr2.push(null);
console.log(arr2);
let arr3:Array<number>=[];
arr3.push(3);
// arr3.push("23");//只能装number类型
arr3.push(6);
// 判断arr3中所有的值是否都小于5
// 检测数组中所有的值是否符合要求
let ok = arr3.every(function(item,index,arr){
return item<5;
})
console.log("ok",ok);
let x = arr3[0].toFixed(2);
console.log(x);
// 多维数组
let sz = [[1,2,[3,4],[5,6],[[7]]]]
console.log(sz[0][2][1]);//4
console.log(sz[2][0][0][0]);//7
元组:
数组里面的值取出来,在类型不明确的情况下,没办法同意调用方法,使用元组,可以提前明确数组每一位的类型。方便调用
// 数组只能装同类型的值
//定义一个元组,可以让数组装不同类型的值
//理论上,元组的值的个数要和声明的类型的个数一致。
let arrs:[number,string,boolean] = [1,"jack",true];
arrs[0].toFixed(3)
arrs[1].substring(1,1);
arrs.push("jasck")
console.log(arrs[0]);
arrs[0]=10;
console.log(arrs);
函数:
map:
ts可以让我们快速的创建map集合
let m2 = new Map([
[3,"jack"],
[4,"mary"]
])
let k = m2.get(3);
console.log(k);
联合类型:
可以让一个变量同时拥有多个类型
let ss:string|number ;
ss = "jack";//ok
ss=123;//ok
// ss=true;//报错
对象:
写对象的时候,可以在对象名后面通过{}
//可以通过大括号来约束对象的属性
// ?表示出现一次或者0次
let obj:{name:string,age:boolean,addr:object,abc?(s:string):string} = {
name:"123",
age:true,
addr:{},
abc:function(){
return "3";
}
}
let xx = obj.abc("ss");
xx.substring(1,1);
// 约束所有的值的类型都市布尔类型
let x1:string = "abcd";
let x2:number = 123;
let obj2:{[propName:string]:boolean} = {
[x1]:true,
[x2]:false
}
console.log(obj2);
// &表示同时
let y1 :{sname:string} & {ages:number} = {
sname:"xx",
ages:18
}
类:
//像这种创建对象的方式,创建的都是Object(对象)类型
let o = {name:"jack",age:12}; //这个对象是什么类型
//检测某个对象是否是某种类的类型
console.log(o instanceof Object); //true,表示o是Object这个类型的对象
//使用new的方式创建的对象,都是具有具体类型的
let d1 = new Date(); //Date这个类型
console.log(d1 instanceof Object); //所有的对象都是对象类型,都是Object类型
console.log(d1 instanceof Date);
console.log(o instanceof Date); //fasle
//创建类
//类是描述对象的
class Person{
name:string;
age:number;
eat(){};
}
//创建一个人对象
let p = new Person();
//设置人的内容
p.name = "jack";
// p.age = "21"; //类型不匹配
p.age = 21;
console.log(p instanceof Person); //true
console.log(p)
//封装一个方法,传一个人进行,就自动调用它的eat方法
function doEat(ren:Person){
ren.eat();
}
let p2 = new Person()
p2.eat = function(){console.log("p2.。吃肉")}
doEat(p2);
class Config{
el:string;
mounted() {
};
computed:object;
methods:object;
}
class Vue{
// 构造方法,
constructor(o:Config){
console.log("tor")
//解析我们穿进去的对象
}
}
// new Vue(); //创建一个对象,实际上就是执行了vue里面的constructor方法,该方法是自动执行的。
let c = new Config();
new Vue(c);
使用构造方法
class Doctor{
name:string;
job:string;
//这个方法是构造方法,这个方法当通过new创建对象的时候就会自动调用
constructor(n:string,job:string){
//this表示当前对象
this.name = n;
this.job = job;
}
}
//创建对象,
let d1 = new Doctor("小明","副主任医师");
console.log(d1);
继承
//定义父类
class Dianqi{
price:number
constructor(price){
this.price = price;
}
}
//定义子类
class Dianao extends Dianqi{
keybord:string //静音键盘
//在子类的构造方法中,必须通过super构造父类的对象
constructor(obj:Dianao){
super(obj.price); // super ==》 Dianqi(); 调用父类的构造方法
//obj {name:"静音键盘",price:999}
this.keybord = obj.keybord;
}
}
//创建子类对象,可以访问父类对象的资源
let dn = new Dianao({keybord:"静音键盘",price:999});
修饰符
xxxxxxxxxx class C1{ //修饰符,作用的控制属性的可见度。谁能用,谁不能用 public name //public修饰属性,表示该属性时公用的。大家都可以访问 private age //表示私有的,只能自己使用 protected addr //表示该子类对象访问的属性}
重写与多态
// 如果一个类里面出现了私有的或者受保护的属性,其他地方又要使用
//可以在类里面提供公共的方法来进行调用。
class C1{
eat(){
console.log("吃肉肉")
}
}
class C2 extends C1{
//子类重写了父类的方法
eat(){
console.log("吃饭饭");
}
}
let c:C2 = new C2();
c.eat(); //吃饭饭
//通过父类类型来接收子类对象,最后调用的方法也是子类的方法。
let c:C1 = new C2();
c.eat(); //吃饭饭。
接口:
接口跟类一样,但是呢,又跟类不一样。
哪儿不一样呢。定义差不多
定义类
class C1{}
定义接口
interface I1{}
哪儿不一样呢?
类里面可以写属性
class C1{
name
age
eat(){}
constructor(){}
}
但是接口里面能写什么呢?
接口里面可以写属性,但是属性不能给值
只能约束属性的类型
interface I1{
sname:string
eat:(a:string,b:number)=>void
}
类是用来创建对象的,接口是用来干什么的?
// 定义接口 -- 接口仅表示类型,不能用来创建对象。
// 它可以作为父类型使用,本身不能创建对象。
// 接口只能起到一个标准作用。
interface I1{
sname:string
eat:(a:string,b:number)=>void
// constructor()
}
// 接口约束了对象的属性,可以写哪些内容,我们都能从提示中看到。
let o:I1 = {
sname:"janck",
eat:function(){
console.log("hello world");
}
}
类可以被多个或者一个接口约束
interface I4 {
sname2
}
interface I5{
abcf
}
class C4 implements I4,I5{
sname2 = "jack"
eat(){}
abc
abcf
def //类是接口类型,但是也可以拥有接口之外的东西
}
接口可以继承另一个接口
interface I4 {
sname2
}
interface I44 {
sname22
}
interface I5 extends I4,I44{
abcf
}
class C4 implements I5{
sname2 = "jack"
sname22=""
abcf
def //类是接口类型,但是也可以拥有接口之外的东西
}
模块:
仅供参考
导出
// 默认导出
export interface SomeInterface{
abc
def
}
导入
import SomeInterface = require('./14-ts-模块')
命名空间:
同一个文件分为两个命名空间
namespace Sp1{
export let sn = "jack";
}
namespace Sp2 {
export let sn = "mary";
}
console.log(Sp1.sn);
console.log(Sp2.sn);
一个文件引用另一个文件命名空间的内容
b文件
namespace Sp3{
export interface p33{
p1
p2
}
}
a文件
/// <reference path= "17-ts-空间.ts" />
class Hello implements Sp3.p33{
p1
p2
}
声明文件:
声明文件是自动加载的,我们编写代码的时候,可以通过声明文件来约束类型,起到提示的作用。
编写声明文件
abc.d.ts
// 通过declare定义
declare let $:(选择器:string)=>Element; //element类型是ts内置的一个类型
实际上,大部分的代码库,为了配合ts,都提供了声明文件,供我们使用,不用我们自己写
npm install @type/jquery
枚举类型:
其实就是将一个有限个数的变量的值一一列举出来。方便使用
例如:黑夜和白天,