js的超集,可以在任何浏览器、计算机和操作系统上运行,但是执行时会先编译成js代码执行。
①、有些错误如:未传参,js在浏览器中编译运行时才会报错,而ts在代码执行前便会报错提示
②、代码提示友好程度更高
③、代码中变量的类型声明使语义更清晰易懂
安装ts:
npm i typescript -g / yarn add typescript -g编译ts文件:
tsc demo.ts //执行后编译生成一个js文件,执行插件:
npm i ts-node / yarn add ts-node插件安装后不需要编译啊,直接ts-node demo.ts即可执行
给变量声明定义静态类型后,变量类型固定不可修改,变量具有该静态类型的所有属性和方法
基础类型:
//null , undefined , symbol , boolean , void const count:number = 123; const teacherName:string = "john";对象类型:
const teacher : { name:string; age:number; } const numbers:number[] = [1,2,3] //数组类型,元素必须为number类型 const getTotal : () => number = () => { return 666; } //函数类型,必须返回一个number类型的结果
type annotation 类型注解 声明变量时,定义类型,告知TS,该变量类型
type inference 类型推断 声明变量时,不定义类型,TS根据变量值推测变量类型
let count: number = 123; let cpunt = 123;注:当确定TS可以分析推断出变量类型时,可以选择类型推断,简化代码,但是当TS无法分析推断出变量类型时,需要类型注解
const firstnum = 1; const secondnum = 2; const sum = firstnum + secondnum; //此时可以选择类型推断实现简化代码 function count(firstnum:number, secondnum:number){ return firstnum + secondnum; } const sum = count(firstnum , secondnum); //此时需要类型注解,因为TS无法推测传入参数的类型实际无论类型注解和类型推断,目的都是让变量有一个具体类型
TS的每一个变量以及每一个对象的属性的类型都是固定的
TS函数相关类型
function count(firstnum:number, secondnum:number):number{ //此处第三个注解是为了防止失误导致返回结果与预期不符 //return firstnum + secondnum + ''; return firstnum + secondnum; } const sum = count(firstnum , secondnum);function sayHello():void{ //void类型表示无返回值 console.log("hello") }function errorEmitter():never{ //error类型表示该函数永远无法执行完,而是执行部分 throw new Error(); console.log(123); }//函数参数解构 //参数传入对象时,在传入时解构 //js function sum({firstnum,secondnum}){ return firstnum + secondnum; } let result = sum({first:1,second:2}) //ts function sum({firstnum,secondnum}:{firstnum:number,secondnum:number}):number{ return firstnum + secondnum; } let result = sum({first:1,second:2})//箭头函数的两种写法 //传入参数为字符类型,返回结果为数值类型 const func = (str:string) => { return parseInt(str,10); } const func1:(str:string) => number = (str) => { return parseInt(str,10); }函数编写时,入参一般需要类型注解,但是返回值往往可以通过类型推断简写
//当一个变量在初始和后续类型不同时,可以通过同时声明多种类型解决 let count : number | string = 123; count = "123";
const mixArr: (number | string)[] = [1,2,'3']; const stringArr : string[] = ['1','2','3']; const undefinedArr : undefined[] = [undefined]; //类型别名 type alias 便于理解 type User = { name:string;age:number}; const objectArr : User[] = [{ name:'kaige', age:18 }]
tuple
//数组 const stipulateArr : (string | number)[] = ['kaige',18,'22'] //元组 //约束规定了数组每项对应的类型 //数组的长度,每个元素对应类型固定时,选择元组会更便于管理 const stipulateArr : [string,number,number] = ['kaige',18,22]
定义通用类型
与类型别名的区别:只能代表函数或对象,无法代表基础类型
interface Person{ name:string; readonly age?:number; //?:语法,表示age属性可有可无,即使传参不具有age属性,也不会报错 readonly只读,不可修改 } type Person1 = string; const getPersonName = (person:Person) => { console.log(person.name) } const setPersonName = (person:Person,name:string) => { person.name = name; }注意:当以字面量形式将对象作为参数传入时,一定要符合类型注解,不能有多余属性,否则会报错
interface Person{ name:string; age?:number; } interface newPerson{ name:string; age?:number; [propName:string]:any; //表示可以存在其他属性,属性名类型为字符,值类型随意 test():string //方法,返回结果为字符类型 } const person = { name:'kaige', gender:'male' } const getPersonName = (person:Person) => { console.log(person.name) } getPersonName(person); //不报错 getPersonName({ name:'kaige', gender:'male' }); //报错 对象字面量传参会进行强校验 //class应用接口 class User implements Person{ name = "kaige"; test(){ return 'aaa' } } //接口定义函数类型 interface test{ ():void } //无参无返回值的函数 let kg : test = () => { console.log('kaige'); } kg();接口interface实际只是TS帮助做语法校验的工具,在编译转化成js代码时,interface的语句会被剔除
class Person { name = 'kaige'; getName(){ return this.name; } } const person = new Person(); console.log(person.getName());super的常用:在子类重写父类方法后,可以通过super调用父类的该方法
//三种访问类型:private protected public //public 允许在类的内外被调用 //private 允许在类内被调用 //protected 允许在类内及继承的子类中使用//constructor class Person { constructor(public name:string){} } //等价于 class Person { public name:string; constructor(public name:string){ this.name = name } } //ts中,调用父类的构造函数时,如果父类的构造函数需要传入参数,还要按照父类构造函数的类型注解规则传入参数,否则会报错 class Teacher { constructor(public name : string){} } class Student extends Teacher { constructor(public age : number){ super('kaige') } } let kg = new Student(22); console.log(kg.name,kg.age)
//作用:调用私有属性,给类的私有属性加密保护//单例模式 class Parent { private static kaige:Parent; //私有化静态属性kaige,Parent类型,只能类内部调用 private constructor(public name : string){}; //私有化构造函数,无法通过new创建新实例 static newParent(){ //静态方法newParent,只能类本身调用 if(!this.kaige) this.kaige = new Parent('kaige'); return this.kaige; } //属性挂载在类身上,实现类似构建新实例对象的效果 } let child1 = Parent.newParent(); let child2 = Parent.newParent(); console.log(child1.name,child2.name) //kaige kaige console.log(child1 === child2); //true //单例模式,获取的是同一个实例对象kaige,第一个实例对象kaige是new构造的
//抽象类只能被继承,不能被实例化 //将共用性的属性、方法抽离成类进行封装abstract class Graph{ abstract getArea() : number } class Circle extends Graph{ getArea(){ return 123; } } class Triangle extends Graph{ getArea(){ return 123; } } class Square extends Graph{ getArea(){ return 123; } } interface Teacher { name:string; } interface Student extends Teacher { age : number; } interface People extends Teacher { gender : string; } let teacher = { name : 'wanggang', } let student = { name : 'kaige', number : 18, } let people = { name : 'xiaopang', gender : "male" } function getName(User : Teacher | Student | People){ console.log(User.name) } //简写 function outputName(User : Teacher){ console.log(User.name) } getName(teacher); getName(student); getName(people); outputName(teacher); outputName(student); outputName(people);