概念
TypeScript是JavaScript类型的超集,它可以编译成纯JavaScript。
TypeScript可以在任何浏览器、任何计算机和任何操作系统上运行,并且是开源的。
使用
手动编译为js
ts文件可以在终端输入
tsc index.ts//ts文件
编译生成一个新的js代码的文件
vscode自动编译为js
在终端输入
tsc --init
生成一个tsconfig.json文件,把文件中的
"outDir": "./", /* 改为 */ "outDir": "./js",
"strict": false, /* 并把严格模式取消 */
在左上角的终端菜单上选择运行任务=>显示所有任务=>选择"tsc监视:xxxxxxx"(该文件名)
然后在当前文件夹中编写ts文件会自动生成js文件夹,包含编译后的js文件
类型注解
一种轻量级为函数或变量添加的约束
(()=>{
function sayHi(str:string){ //此处接收的参数只能是字符串类型并且必须要接受一个参数
return str +" hi"
}
let msg="bob"
console.log(sayHi(msg));
})()
接口
接口的运用
(()=>{
interface IPerson{//定义一个接口
firstName:string,//必须是字符串类型的值
lastName:string
}
function fullName(person:IPerson){//使用接口
return person.firstName+" "+person.lastName
//此处写完person.后会自动弹出firstName和lastName,非常方便且不容易敲错
}
let person1={
firstName:"雾切",//这里的属性名是自定义的,firstName和IPerson接口中的firstName并无关系
lastName:"响子"
}
console.log(fullName(person1));
})()
如果传入的值和接口的不符合,ts中会报错,js中即使不报错,也很可能得不到想要的结果
接口的只读和可选属性
interface IPerson{//定义一个接口
readonly firstName:string,//不能改变firstName的值了
lastName?:string//lastName值现在可有可无
}
一般来说,如果该值当做不需要修改的变量,则加上只读,如果当做属性使用,则加上可选属性
类
(()=>{
//定义接口
interface IPerson{
firstName:string,
lastName:string
}
//定义一个类
class Person{
//定义公共字段(属性)
firstName:string
lastName:string
fullName:string
//定义一个构造器函数
constructor(firstName:string,lastName:string){
this.firstName=firstName
this.lastName=lastName
this.fullName=this.firstName+" "+this.lastName
}
}
function fullName(person:IPerson){
return person.firstName+" "+person.lastName
}
var person=new Person("凯瑟","琳")
console.log(fullName(person));
})()
使用起来和上面的接口是一样的
类的运用
class Person {
name: string;//属性
age: number;
gender: string;
constructor(name: string, age: number=16, gender: string) {
//定义的时候可以对值设置初始化值
this.name = name;
this.age = age;
this.gender = gender;
}
sayHi(str:string){
console.log(`大家好,我是${this.name},今年${this.age}岁了,是${this.gender}孩子`,str);
}
}
let person=new Person("蒋君",23,"男")
person.sayHi("请多多关照")
类的继承
class Person {
name: string;
age: number;
gender: string;
constructor(name: string, age: number, gender: string) {
this.name = name;
this.age = age;
this.gender = gender;
}
sayHi(str:string){
console.log(`大家好,我是${this.name},今年${this.age}岁了,是${this.gender}孩子`,str);
}
}
class Son extends Person{//Son继承Person
constructor(name:string,age:number,gender:string){
super(name,age,gender)//使用super,调用的是父类中的构造函数
}
sayHi(){
console.log("我是son中的方法");
super.sayHi("hhhh")//使用super调用父类中的sayHi方法
}
}
let person=new Person("蒋君",23,"男")
person.sayHi("请多多关照")
let son=new Son("蒋小敏",1,"女")
son.sayHi()
类的修饰符
public 修饰符(默认),代表公共的,在任何位置都可以访问类中的这个成员
private 修饰符,代表私有的,外部无法访问它,包括子类
protected 修饰符,代表受保护的,外部无法访问它,但子类可以
readonly修饰符
class Person{
public name:string //公共的
private age:number //私有的
protected gender:string //受保护的
readonly size:number //只读的
//............
}
constructor和方法前同样可以加修饰符
使用webpack打包ts
参考:webpack打包ts
ts基础类型
let flag:boolean=true
let num:number=1111
let str:string="aaaa"
console.log(flag+"*"+num+"*"+str);
基础类型本质上和js并没有什么区别
ts中变量一开始是什么类型,后期赋值就只能用这个类型,例如上面的flag就不能赋值为10,只能赋值为true或者false
null和undefined
null和undefined可以作为其它类型的子类型,如
let nll:number=null//如果报错,把tsconfig.json中的严格模式关闭即可
console.log(nll);
数组类型
有三种定义方式
let arr1:number[]=[1,2,3]
let arr3:[number,string,boolean]=[1,"a",true]//元组类型:在定义的时候,类型和数据个数就已经定下了
let arr2:Array<string>=["a","b","c"]//泛型写法
枚举类型
枚举类型中每个值都可以叫元素,它们都有自己的编号,默认从0开始,往后递增
enum Color{
red,//0
blue,//1
green//2
}
let color:Color=Color.red
console.log(color);
也可以自定义指定
enum Color{
red=10,//这样就会从10开始递增
blue,//11
green//也可以green=100
}
枚举中的值可以是中文,但不推荐这样做
any类型
当不确定当前值是什么类型的时候,用any,它可以存储任意类型值
let str:any="aaa"
str=123//可以运行
//或是
let arr:any[]=[123,"aaa"]
void类型
没多大意义,就是告诉别人这个函数没有返回值
function fn():void{
console.log("hhh");
return
}
fn()
object类型
function obj(obj:object):object{//参数和返回值都是object类型
console.log(obj);
return
}
联合类型
function getStr(str:number|string):string{//这种方式既可以传number类型,也可以传string类型
console.log(str.toString());
return
}
getStr(111)
函数类型
为了使用接口表示函数类型,需要给接口定义一个调用签名,它就像是一个只有参数列表和返回值类型的函数定义,参数列表中每个参数都需要名字和类型
interface ISearchFun{
(source:string,subString:string):boolean
}
const searchString:ISearchFun=function(source:string,subString:string):boolean{
return source.search(subString)>-1 //在source中查询是否有subString
}
console.log(searchString("你是个好人","好"));
函数
函数重载
函数名字相同,函数的参数及个数不同
function fn(x: string, y: string): string;//函数重载声明
function fn(x: number, y: number): number;//函数重载声明
function fn(x: string | number, y: string | number): string | number {
if (typeof x === "string" && typeof y === "string") {
return x + y;
} else if (typeof x === "number" && typeof y === "number") {
return x + y;
}
}
console.log(fn("a", "b"));//ab
console.log(fn(1, 2));//3
泛型
在定义函数,类,接口的时候不能预先确定要使用的数据的类型,而是在使用的时候才能确定数据的类型
function getArr<T>(x: T, counts: number): T[] {//T为自定义的
var arr:Array<T>=[];
for (var i = 0; i < counts; i++){
arr.push(x)
}
return arr
}
var arr1=getArr("a",3)
var arr2=getArr(1,3)
console.log(arr1);
console.log(arr2);
多个泛型参数的函数
function arr<T,F>(x:T,y:F):[T,F] {
//............
return
}