TS是对js语言的一种规范,如果没有TS,首先js语法过于自由,这就导致往往出错之后,难以排错,从而出现,维护成本高于重构成本。它是对js的一种扩展,最终还是要编译成js代码,再在浏览器中解释运行。
npm install -g typescript
//1.声明a为string类型
let a:string;
//a = 23;//报错
a = "我爱你";
//2.直接声明类型后赋值或者直接赋值,都能起到限制类型的作用
let b: 3|4|"我爱你" = 4;
//let c: 3|4|"我爱你" = 1;//报错,因为没有在字面量限制中,故无法成功。
//3.函数中类型的声明
function me(a:number,b:string):number{
return a;
//参数中规定参数的类型,后面number规定返回值类型。
};
//3.1在声明函数前,规定函数的参数类型和返回值
let meTwo: (a:number,b:string,[args]:any)=>number;
meTwo = function(a,b,r){
return a;
//[args]:any,意为不限制传入参数个数,随意。
}
//4.对象中属性类型的限制
//因为在js中函数和对象是混为一谈的,所以在ts中对象应该如下声明:
let e:{ name: string, age:number};
e = {
name:"托尼",
age: 18
//上面方式无法再声明其他属性
}
//4.1如何仅限定必要属性,而不影响未规定属性的添加?
let f: {name:string,age:number,[xx:string]:any}
//意为规定必须有name和age属性,但是其他属性名只要是string类型,值可以是随意,即实现了我们预想的效果。
f = {
name: "华为",
age: 23,
lover: "小米"
}
//5.枚举类型
enum g{
mele=0,
female=1
}
let h: {name: string,gender:g}
h={
name: "托尼",
gender:g.female,
}
//6.类型的别名常用于自定义字面量类型
type myType = 1|3|"我爱你";
let i: myType;
{
"include":["../MYTS/**/*"],//指定要编译的文件路径 **表示任意文件夹 * 表示任意文件
"exclude": [],//一般不用,会有默认值将一些不需要编译的包排除在外。
//"files": [],//指定要被编译的文件列表
"compilerOptions": {
//指定编译后的js文件所在的目录
"outDir": "../compilerOptions",
//outFile,将编译后的代码合并到一个文件输出,注意这里不支持使用es6模块化的ts文件进行合并
//"outFile": "",
//是否对js文件进行编译,默认是false
"allowJs": true,
//是否检查js代码是否符合语法规范,默认是false
"checkJs": false,
//是否移除注释
"removeComments": false,
//当有错误时不生成编译后的文件
"noEmitOnError": false,
//alwaysStrict,用来确定编译完毕的js代码是否使用严格模式,
"alwaysStrict": true,//注意如果使用模块化,将自动使用严格模式。
//不允许隐式的any类型
"noImplicitAny": true,
//不允许没有明确指向的this
"noImplicitThis": false,
//严格检查空值
"strictNullChecks": false,
//所有严格检查的总开关
// "strict": false
}
}
function myFunction(){
console.log(this);
}//不知道何人调用,就是指向不明确
let button = document.getElementById("box1");
button.addEventListener("click",()=>{
alert("one");
})
//存在box1这个元素不存在的隐患
解决:
let button = document.getElementById("box1");
//1.加上判断
if(button != null){
button.addEventListener("click",()=>{
alert("one");
})}
//2.使用修饰符
button?.addEventListener("click",()=>{
alert("one");
})
npm init -y
后产生文件package.json
npm install -D webpack webpack-cli typescript ts-loader
下载完毕后,就会在文件夹中多出两个,一个文件夹node_modules,一个文件package-lock.json
let path = require("path");
module.exports = {
//指定入口文件
entry: "./src/myFirstTest.ts",
//指定打包文件所在目录
output:{
//指定打包文件的目录
path: path.resolve(__dirname,'dist'),
//打包后文件的文件
filename: "bundle.js"
},
mode: "production",
//指定webpack打包时要使用的模块
module:{
///指定要加载的规则
rules:[
{
//test指定的是规则生效的文件
test: /\.ts$/,
//要使用的loader
use: 'ts-loader',
//要排除的文件
exclude: /node_modules/ ,
}
]
}
}
最后根据配置文件中的入口地址等信息,将对应文件放在对应位置,同时ts配置文件也要声明正确的路径,这里我是把入口文件放在了src文件夹中了。
这里的dist文件夹还未生成!
npm run build
npm install html-webpack-plugin
let HtmlWebpackPlugin = require("html-webpack-plugin");
//下面省略的其他配置
module.exports = {
//使用插件
plugins:[
new HtmlWebpackPlugin({
title:"我的第一个页面",//自定义选项,可选
template: ""//指定自定义html模版的路径,那么生成的html文件就会跟指定的html文件一致。
}),
]
}
npm install -D webpack-dev-server
"start": "webpack serve --open --mode production"
npm install -d clean-webpack-plugin
//引入clean-webpack-plugin
let {CleanWebpackPlugin} = require("clean-webpack-plugin");
module.exports = {
//使用插件
plugins:[
new CleanWebpackPlugin,
]
}
默认webpack不知道ts也可进行模块化引入,所以要在webpack.config.js加入配置
resolve:{
extensions:[".ts",".js"],//指定后缀为js或者ts的都可以作为模块
}
总述:总的来看,js现在在新的es标准中增加了类,ts在js增加的类的基础上又增加了其他几种,更加完善和完备。这里学过java的对这些概念的理解会比较快!
类和对象的关系就像动物和狗、猫等的关系,对象的抽象叫做类,类的具体实现叫做对象。
类的声明方式如下:
//声明一个类
class myClass{
//类中非静态方法中的this指向都是其具体创建的对象
name: string="我是谁?";
lover: string = "灵儿";
readonly say:string="谁都改不了"; //readonly 属性对象创建后只能读取不能修改
static meOnlyHave: number = 33;//静态属性可以直接通过类调用,但是不能通过对象调用。
//构造函数,用类创建对象时,一定会调用的方法,通过该方法传入对象具体的细节。
constructor(name:string,lover:string){
this.name = name;
this.lover = lover;
}
//声明一个方法
iLoveDo(a:number,b:number){
if(a + b == 2){
console.log("我最爱的两个数字是" + a + "和" + b + "\n因为他们加起来是2" + "我最喜欢的一部动漫的女主的编号" );
}else {
console.log(a + b);
}
}
}
//声明一个具体的对象
let myClassObject = new myClass("广","灵儿");
myClassObject.iLoveDo;
class InMyClass extends myClass{
//继承了myClass类后,就直接拥有了其父类的方法和属性
//也可以声明自己的属性和方法
dream:string = "成为更好的自己!";
//构造函数中使用super()让创建对象时给父类继承的属性赋值
constructor(name:string,lover:string,dream:string){
super(name,lover);
this.dream = dream;
}
doDream(){
console.log("唯有拼搏努力!");
//可以在子类方法中通过super调用父类方法,从而强化父类方法
super.iLoveDo(0,2);
}
//(重写)当子类的方法名和父类继承的一样时,子类方法覆盖父类方法
iLoveDo(a: number, b: number): void {
console.log("哈哈,我修改了父类方法,我就是王者!")
}
}
抽象类的出现就是为了继承,它不能被创建实例(对象),里面可以定义具体的属性和方法,也可以规定抽象的属性和方法,这些抽象的方法和属性在继承时,必须被继承者重写。
声明:
//声明一个抽象类
abstract class meAndYou{
//声明抽象属性和方法
abstract name:string;
abstract loveGirl(name:string):void;
//声明具体的方法和属性
lover: string = "灵儿";
doThings(name:string){
console.log("我爱的人是:" + name);
}
}
接口是对类结构进行的一种规范,里面不能进行具体的逻辑书写。
//声明一个接口
interface animal{
name:string;
age:number;
doTo:string;
isFemale:boolean;
do(detail:string,animalType:string):void;
}
//实现接口
class dog implements animal{
name:string ="Tom";
age:number=23;
doTo:string="舔";
isFemale:boolean= true;
do(detail:string,animalType:string):void{
console.log("me");
}
}
//封装一个属性
class people{
private name:string = "托尼";//该属性是私有属性,只能在该类中调用。
constructor(){
}
//通过方法实现外部调用和修改
getName(){
return this.name;
}
setName(name:string){
this.name = name;
}
//使用getter和setter实现私有属性的发现和修改
get _name(){
return this.name;
}
set _name(name){
this.name = name;
}
}
let toni = new people();
//私有属性不能直接调用
//console.log(toni.name);//报错
toni._name = "水门";//通过setter设置name
console.log(toni._name);
toni.setName("波风"); //通过方法设置name
console.log(toni._name);
//即使在其子类中也不能直接调用
class goodBoy extends people{
age: number;
protected lover: string;
//使用protected修饰的属性只能在自己及子类中使用,不能在实例对象中使用
constructor(age:number){
super();
this.age = age
}
getFatherName(){
// this.name;//报错
console.log(this._name);
}
}
为了确认函数输入和输出结果结构的一致性。
//声明一个简单的泛型
function meMe<T>(hh: T):T{
return hh;
}
//使用
meMe<string>("我是波风水门");
//泛型的继承
function meMeMe<T extends goodBoy>(hh:T): T{
return hh;
}
//使用
meMeMe<goodBoy>(new goodBoy(33));