环境安装
ts解释器是用node.js 写的
npm 是node安装包管理工具
执行ts文件:
- 进入命令行
- 进入ts文件所在的目录
- 执行命令: tsc xxx.ts
- 然后会编译成一个新的js文件
tsc 文件名
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lESEbWEU-1643186500112)(D:\资料\web笔记\TypeScript\image\TypeScript\image-20210927141813250.png)]
基本语法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R9KnW9Uo-1643186500120)(D:\资料\web笔记\TypeScript\image\TypeScript\image-20220118111832051.png)]
类型声明:语法
let 变量: 类型;
let 变量: 类型 = 值;
function fn(参数: 类型, 参数: 类型) :类型 {
...
}
(js的变量是没有类型 的)
-
声明一个变量a,同时指定它的类型是number
-
let a : number
-
-
声明变量直接进行赋值
-
let b:string = 'hello';
-
-
如果变量的声明和赋值是同时进行的,TS可以自动对变量进行类型检测
-
let c = false c = 123 // 会报错, 因为此时的c已经是boolean类型了
-
-
函数的参数/返回值 指定类型
-
function sum(a:number, b:number) { return a + b } sun (123, 456) sun (123, '456') // 报错 //函数返回值的类型 function sun(a:number, b: number): number { return a + 'hello' // 报错 }
-
-
字面量(也可以直接使用字面量进行类型声明)
-
let a: 10 a = 10; a = 11; // 报错,a已经被赋值为10了,相当于常量 // 可以使用 | 来连接多个类型(联合类型) let b: "male" | "female"; “|”==》或 b = "male" b = "female" b = "hello" // 报错 let c: boolean | string; c = true; c = 'hello'
-
-
any (任意类型)一个变量设置类型为any后相当于对该变量关闭了TS的类型检测(使用ts是,不建议使用any类型)
-
let d: any; d = 10; d = "hello"; d = true
-
声明变量如果不知道类型,则TS解释会自动判断变量的类型为any (隐式的any)
-
let d; d = 10; d = "hello"; d = true
-
-
-
unknown:表示未知类型的值
-
unknown 实际上就是一个类型安全的any
-
unknown 类型的变量,不能直接赋值给其他变
-
any类型的变量可以赋值给其他变量(不严谨)
-
let a:any let s:string s = a; // 不报错,后期很危险 let c:unknown let d:string d = c , 会报错 //如果c非要赋值給d该如何处理 作判断后再赋值 if(typeof c==='string') { d=c }
-
-
类型断言,可以用来告诉解释器变量的实际类型
-
语法: 变量 as 类型 或者 <类型>变量
-
let e:unknown; let s:string; s = e as string; s = <string>e;
-
-
void 用来表示没有值或者undefind,与函数为例,就表示没有返回值的函数
-
function fn():void{ return undefind/null; return }
-
-
nerver 表示永远不会返回结果(可用来报错处理) 程序或者函数报错了代码会立即结束
-
function fn2():never{ throw new Error('报错啦') }
-
-
object表示一个js对象
-
{}用来指定对对象中可以包含那些属性
-
语法:{属性名:属性值,属性名:属性值}
-
在属性名后面加上"?",表示属性是可选的
-
let b:{name:string, age?:number} b = {name:'lihua',age:18} //name属性必有,age可选
-
[propName: string] :any 表示任意类型的属性
-
let c:{name:string,[propName:string]:any}; c={name:'lihua',age:18,gender:'男'}
-
设置函数结构的类型声明:
-
语法:(形参:类型,形参:类型 …)=> 返回值
-
let d:(a:number,b:number):number{ return 10 }
-
-
-
array
-
数组的类型声明:
- 类型[]
- Array<类型>
-
//string[] 表示字符串数组 let e:string[]; e = ['a','b','c']; //number[] 表示数值数组 let f: number[]; f = [1,2,3] let g:Array<number> g = [1,2,3]
-
-
元组,元组就是固定长度的数组
-
语法:[类型,类型,类型]
-
let h:[string,number] h = ['lihua',123]
-
-
enum 枚举
-
null
-
enum Gender:{ Female=0 Male = 1 } let i:{name: string,gender:Gender} i = { name:'lihua', gender: Gender.Male }
-
-
& 表示同时
-
let j:{name: string} & {age: number} j={name:'lihua',age:18}
-
-
类型的别名
-
type myType = 1|2|3|4|5 let k:myType; let j:myType;
-
-
null
编译选项
自动编译文件
-
编译文件时,使用 -w 指令后,TS编译器会自动监视文件的变化(watch),并在文件发生变化时进行重新编译
-
示例:
-
tsc xxx.ts -w
-
null
-
自动编译整个项目
-
根目录下,新建tsconfig.json 文件
-
“include” 用来指定那些ts文件需要编译
- 路径: ** 表示任意目录 / * 表示任意文件
-
“exclude” 不需要被编译的文件目录
- 默认值:[“node_modules”,“bower_components”, “jspm_packages”]
-
“complierOptions” 编译器选项 (如果不知道有哪些值可以填的话,可以随便填个错误的,看报错提示,会提示有哪些可选值)
- target :用来指定ts被编译为的ES的版本
- 可选: “es3”,“es5”,“es6”,“es2015”,“es2016”,“es2017”,“es2018”,“es2019”,“es2020”,“es2021”,“ESNext”, “ESNext”:最新版本
- lib : 用来指定项目中个要使用的库/宿主环境 (一般不用修改)
- module: 用来指定要使用的模块化的规范
- 可选: “none”,“commonjs”,“amd”,“system”,“umd”,“es6”,“es2015”,“es2019”,“es2020”,“esnext”
- outDir:用来指定编译后文件所在的目录,
- outFile: 将代码合并为一个文件 (所有的全局作用域中的代码会合并到同一个文件中) 用的不多,一般会结合打包工具
- 配置的话还要把moudle的值改为amd或者system
- allowJs:是否对js文件进行编译,默认是false
- checkJs: 是否检查js代码是否符合语法规范,默认是false
- removeComments: 是否移除注释 ,默认是false
- noEmit: 不生成编译后的文件 ,默认是false
- noEmitOnError: 当有错误时不生成编译后文件 ,默认是false
- alwaysStrict : 用来设置编译后的文件是否使用严格模式,默认是false
- noImplicitAny : 不允许隐式的any类型(假如我们变量忘记声明类型,浏览器判断为any类型,这种为隐式any),默认是false
- noImplicitThis:不允许不明确类型的this,默认是false
- strictNullChecks:严格的检查空值,默认是false 比如获取某个不存在的东西(document.getelementById(‘root’)) (访问一个对象没有的属性)
- strict:所有严格的总开关,默认是false //平常开这么一个就可以了,上面的严格模式基本都开了
- null
- target :用来指定ts被编译为的ES的版本
-
null
-
//tsconfig.json { "include":[ "./src/**/*" ], "exclude":[ "./src/hello/**/*" ], "compilerOptions":{ "target":"es6", "module":"es2015", "lib":["ES6","DOM"], "outDir": "./dist", "outFile": "./dist/app.js", "allowJs":true, "checkJs":true, "removeComments":true, "noEmit":true, "noEmitOnError":true, "alwaysStrict":true, "noImplicitAny ":true, "noImplicitThis":true, "strictNullChecks":true, "strict":true } }
-
null
webpack打包
安装依赖 cnpm i -D -D:开发依赖
-
安装所需的依赖:
-
webpack :webpack核心包
-
webpack-cli :webpack的命令行工具
-
typescript :ts核心包
-
ts-loader
-
html-webpack-plugin :帮助我们自动的生成html
-
webpack-dev-server :相当于安装内置服务器,自动刷新
-
clean-webpack-plugin: 清空dist目录,重新生成打包文件
-
@babel/core
-
@babel/preset-env
-
babel-loader
-
core-js
-
cnpm i -D webpack webpack-cli typescript ts-loader html-webpack-plugin webpack-dev-server clean-webpack-plugin @babel/core @babel/preset-env babel-loader core-js
-
-
根目录新建 webpack.config.js 配置文件
-
// webpack.json.js // 引入一个包 const path = require('path') //引入html插件 const HTMLWabpackPlugin = require('html-webpack-plugin') //引入clean 插件 const {CleanWebpackPlugin} = require('clean-webpack-plugin') // webpack 中的所有的配置信息都应该写在module.exports中 module.exports = { //指定入口文件 entry: "./src/index.js" //指定打包文件所在目录 output: { //指定打包文件的目录 path:path.resolv(__dirname,'dist'), 或者直接"./dist" //打包后的文件名 filename: "bundle.js", //告诉webpack 不使用箭头函数 environment:{ arrowFunction:false } }, //指定webpack打包时要使用的模块 module:{ // relus:[ { //test指定的是规则生效的文件 test: /\.ts$/, //匹配ts结尾的文件 //配置babel use:[ //重下往上执行,先ts转js,再用bable转 'babel-loader' { //指定加载器 loader:'babel-loader', //设置babel options:{ //设置预定义的环境 presets:[ //指定环境的插件 "@babel/preset-env", //配置信息 { //要兼容的目标浏览器 targets:{ "chrome":'88', "ie":"11" }, //指定core.js 的版本 "corejs":'3', //使用corejs的方式"usage"表示按需加载 "useBuiltIns":"usage" } ] } } //要使用的loader 'ts-loader', ] //要排除的文件 exclude:/node-modules/ } ] }, //配置webpack插件 (自动生成html文件) plugins: [ new CleanWebpackPlugin(), new HTMLWebpackPlugin(option:{ title:"自定义title" }), ], //用来设置引用模块 resolve: { extensions:['.ts','.js'] //凡是以.ts /.js结束 的都可以作为模块引用 } }
-
null
-
-
最后一步在package.json 配置打包命令
-
{ "scripts":{ //打包命令 "build":"webpack", //启动webpack服务,并且用chrome浏览器打开(监听文件,自动重新构建刷新页面) "start":"webpack serve --open chrome.exe" } }
-
-
打包命令
-
npm run build npm start
-
面向对象
类
构造函数和this
-
class Dog { name:string; age: number; // constructor 被称为构造函数 //构造函数会在对象创建时调用 constructor(name:string, age:number){ //在实例方法中,this就表示当前的实例 //在构造函数中当前对象就是当前新建的那个对象 //可以通过this向新建的对象中添加属性 //console.log('被调用执行。。。') this.name = name this.age = age } } //调用new Dog 构造函数会被调用 此时的this就是dog const dog = new Dog(name:"huage1",age:17); //调用new Dog 构造函数会被调用 此时的this就是dog2 const dog2 = new Dog(name:"huage2",age:18); console.log(dog)
extends继承
-
(function (){ //定义一个Animal { name: string; age: number; constructor(name:string,age:number) { this.name: name; this.age: age; } } //Dog extends Animal //此时,Animal被称为父类,Dog被称为子类 //使用继承后,子类将会拥有父类所有的方法和属性 //通过继承可以将多个类中共有的代码写在一个父类中 //这样只需要写一次即可让所有的子类都同时拥有父类中的属性 //如果希望在子类中添加一下些父类中没有的属性或方法直接加载子类中 //定义一个表示狗的类 //是Dog类继承Animal类 class Dog extends Animal { run(){ console.log('Dogd独有') } } //定义一个表示猫的类 //Cat 类继承Animal类 class Cat extends Animal { } const dog = new Dog(name:'旺财', age:5) const cat = new Cat(name:'猫咪', age:4) dog.run() })()
super关键
(function (){
class Animal {
name: string;
constructor(name:string) {
this.name = name
}
sayHello(){
console.log('hahaha')
}
}
class Dog extends Animal {
sayHello(){
// 在类的方法中 super就表示当前类的父类
super.sayHello() // 实际是调用父类的sayHello
}
}
const dog = new Dog(name:'huage');\
dog.sayHello(); //打印出来 ‘hahaha’
})()
(function (){
class Animal {
name: string;
constructor(name:string) {
this.name = name
}
}
class Dog extends Animal {
age:number
//这里又写了一个constructor相当于把父类的constructor重构了,就不会执行父类的constroutor了
//如果在子类中写了构造函数,在子类构造函数中必须手动对父类的构造函数进行调用
//注意这里一定要把父类构造函数的参数name传进来
constructor(name:string,age:number) {
super(name); //调用父类的构造函数 //注意这里一定要把父类构造函数的参数name传进来
this,age = age
}
sayHello(){
console.log('lalala')
}
}
const dog = new Dog(name:'huage',age:18);\
dog.sayHello(); //打印出来 ‘hahaha’
})()
abstract抽象类
- 以abstract开头的类是抽象类
- 抽象类和其他类的区别不大,只是不能用来创建对象
- 抽象类就是专门用来被继承的类
- 抽象类可以添加抽象方法
- 抽象方法使用abstract开头,没有方法体
- 抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
(function (){
abstract class Animal {
name: string;
constructor(name:string) {
this.name = name
}
sayHello(){
console.log('动物在叫。。。')
}
}
class Dog extends Animal {
sayHello(){
console.log('喵喵')
}
}
const dog1 = new Animal(name:'猫仔'); // 错误写法,抽象类不能创建对象
const dog = new Dog(name:'猫仔');
dog.sayHello(); //打印出来 ‘hahaha’
})()
//抽象方法
(function (){
abstract class Animal {
name: string;
constructor(name:string) {
this.name = name
}
//定义一个抽象类
//抽象方法使用abstract开头,没有方法体
//抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
abstract sayHello():void
}
class Dog extends Animal {
//子类不重新抽象类会报错,必须重写抽象方法
sayHello(){
console.log('喵喵')
}
}
const dog = new Dog(name:'猫仔');
dog.sayHello(); //打印出来 ‘hahaha’
})()
interface接口
- null
(function(){
//描述一个对象的类型 只能声明一个myType, 不能重复声明对象的类型,
type myType = {
name: string,
age: number,
[propname:string]: any
};
const obj:myType = {
name: 'hauge',
age: 18,
gender:'nan'
}
//接口可以当成类型声明去使用
//同时接口用来定义一个类结构,用来定义一个类中应该包含哪些属性和方法
//可以重复声明,最后两个合在一起
interface myInterface {
name: string,
age: number
}
interface myInterface {
gender: string
}
const obj: myInterface = {
name: 'huage1',
age: 18,
gender:'nan
}
//接口可以在定义类的时候去限制类的结构(有点类型抽象类
//接口中的所有的属性都不能有实际的值
//接口只定义对象的结构,而不考虑实际值
//在接口中所有的方法都是抽象方法
interface myInter {
name: string;
sayHello():void;
}
//定义类时,可以使类去实现(implements)一个接口,】
//实现接口就是使类满足接口的要求
class MyClass implements myInter {
name: string;
//用构造函数来初始化name
constructor(name:string){
this.name: string
}
sayHello(){
console.log('hello')
}
}
})()
泛型
//使用any会关闭类型判断,(没意义)
function fn(a:any):any {
return a;
}
//在定义函数或是类时,如果遇到类型不明确就可以使用泛型
//T表示任意类型
//T只有在运行时才知道是什么类型
function fn1<T>(a:T):T {
return a;
}
//可以直接调用具有泛型的函数
fn1(a:10) //不指定泛型,TS可以自动对类型进行推断,把number类型赋值给T (这里会自动判断出T的类型时number)
fn1<string>(a:'hello') //指定泛型 ,手动指定泛型是字符串
//泛型可以指定多个
//指定两个泛型
function fn2<T,K>(a:T, b:K):T {
return a
}
fn2(a:123,b:'hellog') //自动推断类型
fn2<number,string>(a:123,b:'hellog') //手动指定类型,降低出错率
//新建一个接口
interface Inter {
length:number
}
//T entends Inter 表示泛型T必须是Inter实现类(子类)
function fn3<T entends Inter>(a:T):number {
return a.length
}
fn3(a:'123') // 有length属性
fn3(a:123) //报错,没有length属性
fn3(a:{length:10}) //这样也可以
//新建一个类
class MyClass<T> {
name:T;
construcotr(name:T) {
this.name = name
}
}
const mc = new MyClass(name:'孙悟空') //自动推断
const mc = new MyClass<srting>(name:'孙悟空') //指定类型