- TypeScript 由微软研发,以JavaScript为基础构建的语言,它是js的一个超集,可以在任何支持js的平台中执行,但它不能被js解析器直接执行,需要经过编译成js执行,ts扩展了js
- ts添加了类型
- ts 支持ES的新特性
- 添加ES不具备的新特性
- 丰富的配置选项,可以支持特定版本的es
-
使用
tsc ***.ts
命令可以将ts文件编译成js -
定义变量格式:
let 变量名: 类型 = 初始值;
-
类型名首字母小写:
类型string, number, boolean
-
函数定义格式
function 函数名(参数名:参数类型, 参数名:参数类型): 返回值类型 {
}
- 如果变量的声明和赋值同时进行,ts会自动对变量进行类型检测
- 可以直接使用字面量进行类型声明
let 变量名: 字面量值
, 比如:let a: 10
,就是指定a的值只能是10, 如果给a赋值别的值,会报错,比如 a=11;就会报错. 这种常用于使用 | 连接多个值给字面量赋值,比如let b: "male" | "female";
这样定义后 b的值只能是"male" 或者 "female"而不能是其他值 - 使用 | 连接多个类型称为联合类型, 比如
let c: boolean | string;
定义了一个变量c ,这个c 只能赋值boolean或string类型的值 - any 表示是任意类型,相当于关闭了TS的类型检测, 声明一个变量,不指定类型,没有赋初始值的时候,默认就是any类型
- unknown 表示类型安全的any, 它于any的区别在于any类型的变量可以赋值给任何类型的变量, 而unknow类型的变量不能赋值给其他类型的变量,
let s:string="a";
let u:unknown;
u = "str";
s = u; // 报错,不能将unknown类型的变量赋值给string类型的变量
// 可以通过下面的方式赋值
if(typeof u==="string"){
s = u;
}
// 也可以通过下面类型断言的方式赋值
s = u as string;
s = <string>u;
- 类型断言有两种方式:
- 一种是:
变量 = unknown类型变量 as 变量的类型;
, 比如s = u as string;
- 一种是:
变量 = <变量类型>unknown类型变量;
,比如s = <string>u;
- 一种是:
- never: 表示永远不会返回结果
- 属性名后面加?表示该属性是可选属性, 有也可以没有也可以,如下:
let b:{name: string, age?: number}
b = {name:'孙悟空'}; //可以
b = {name:'孙悟空', age:18}; //可以
b = {name:'孙悟空', age:18, gender:'male'}; //不可以
- 任意类型属性: 对象中使用[: string]: any, 表示任意类型的属性都可以,可以随便写, string指的是属性的key使用string类型, any表示属性可以是任意类型,比如
let c: {name: string, [propsName: string]:any}
c = {name:"孙悟空", age:18, gender:"female"};//可以
c = {age=18,gender="female"};// 不可以,其他属性随意,但必须要有name属性
- 数组的两种表达方式:
- 一种是:
类型[]
, 比如:let e: string[] = ['a','b','c'];
- 一种是:
Array<类型>
, 比如:let g: Array<number> = [1,2,3];
- 一种是:
- 元祖, 就是固定长度的数组
let h: [string, string];
h = ["hello","world"];//可以
h = ["hello","world","!"];//不可以, 长度不对
h = ["hello"];//不可以, 长度不对
h = ["hello",123];//不可以, 元素类型不对
- 枚举
- & 用法, 表示同时满足
let j: {name:string} & {age:number};
j = {name:""孙悟空} & {age:18}; // 可以
j = {name:""孙悟空} ; // 不可以,没有满足{age:number}
j = {age:18} ; // 不可以,没有满足{name:string}
tsconfig.json 配置
- 使用 type 定义类型别名
type myType = string
, myType就相当于string, 通常给联合类型设置别名type myType = 1 | 2 | 3 | 4 | 5;
-
tsc ***.ts -w
,加上-w后会自动监视文件的变化,不用每次都执行tsc ***.ts进行编译产生js文件, 这种方式也很麻烦,如果我们有100个ts文件在改动,那么需要执行一百次这个命令去监视一百个文件的改动 - 在根目录执行tsc 命令会一次性编译所有的ts文件
- 我们可以通过在根目录配置tsconfig.json文件的方式,来配置需要编译的文件信息,tsconfig.json 是ts编译器的配置文件,ts编译器可以根据它里面的配置信息来对代码进行编译
- ts 编译器不会将导入的但没用到的变量编译成js的
include
- include 用来指定哪些ts文件需要被编译,如果为空,表示所有ts文件需要编译
"include" : [
"./src/**/*" //这里两个*表示任意目录,一个*表示任意文件
]
exclude
- exclude用来指定哪些ts文件不需要编译
"exclude" : [
"./src/hello/**/*" //这里表示src/hello目录下的所有ts文件都不需要编译
]
extends
- extends 定义被继承的配置文件, 比如别的地方已经有一个***.json文件里配置的需要编译的文件信息,那么就可以使用extends将别的文件里的配置信息继承过来, 比如
"extends": "./configs/base"
files
- files 指定被编译文件的列表,只有需要编译的文件少时才会用到,比如
"files":[
"core.ts",
"sys.ts",
"types.ts",
...
]
compilerOptions
- target: 用来指定编译为ES的版本
"target": "es3" // 指定编译为ES3 版本
, target 值不能是随意的,只能是指定的 'es3','es5','es6','es2015','es2016','es2017','es2018','es2019','es2020','esnext',如果不是,编译后会提示 - module: 指定要使用的模块化的规范,
"module":"es2015"
- lib: 用来指定项目中要使用的库,默认
["es6","dom"]
一般不需要改 - outDir: 用来指定编译后文件所在目录,
"outDir":"./dist"
- outFile: 可以将我们所有的全局作用域的代码合并为一个文件,
"outFile":"./dist/app.js"
- allowJs: 是否对js文件进行编译,默认是false,
"allowJs":false
- checkJs: 是否检查js代码是否符合语法规范,默认是false,
"checkJs":false
- removeComments: 是否移除注释
- noEmit: 不成编译后的文件,true 表示不生成,false 表示生成
- noEmitOnError: 有错误时不生成编译后的文件,true表示不生成,false表示生成
- alwaysStrict: 用来设置编译后的文件是否使用严格模式,默认false
- noImplicitAny: 不允许隐式的any类型,默认false
- noImplicitThis: 不允许不明确类型的this,默认false
- strictNullChecks: 严格的检查空值
- strict: 所有严格检查的总开关
webpack 打包ts代码
- 使用
npm init -y
命令在根目录下生成package.json文件 - 使用
npm i -D webpack webpack-cli typescript ts-loader
命令安装webpack和依赖的包, i 表示安装, -D表示开发依赖, webpack-cli是webpack的命令行工具 , typescript 是ts的核心包,ts-loader是webpack的加载器,通过ts-loader可以把我们的ts代码和webpack进行整合 - 新建webpack.config.js
const path = require('path') // 引入path包
const HTMLWebpackPlugin = require('html-webpack-plugin'); //引入html 插件
const CleanWebpackPlugin = require('clean-webpack-plugin'); //引入插件
// webpack 中的所有配置信息都应该写在module.exports中
module.exports = {
// 指定入口文件
entry: "./src/index.ts",
//指定打包文件所在目录
output:{
// 指定打包文件的目录
path: path.resolve(__dirname,'dist'),
// 打包后的文件
filename:"bundle.js"
},
// 指定webpack打包时要使用模块
module:{
//指定要加载的规则
rules:[
{
// 指定规则生效的文件
test:/\.ts$/,
// 要使用的loader
use:'ts-loader',
// 要排除的文件
exclude:/node-modules/
}
]
}
plugins:[
new HTMLWebpackPlugin(
options:{
title:"自定义title"
}
),
new CleanWebpackPlugin(),
],
// 用来设置引用模块
resolve: {
extensions: [ '.ts', '.js'], // 凡是以ts,js 结尾的文件都可以作模块使用
}
}
-
创建tsconfig.json指定ts的编译规范
-
在package.json文件的scripts中,加入
"build":"webpack"
-
执行
npm i -D html-webpack-plugin
这个插件自动帮我生成html文件,并引入相关资源, -
执行
npm i -D webpack-dev-server
,安装webpack的开发服务器,它可以根据项目的改变自动刷新, 安装完成后需要在package.json文件的scripts中,加入"start":"webpack server --open chrome.exe"
-
执行
npm i -D clean-webpack-plugin
,它可以帮我们在每次编译前将dist文件清空, 然后将编译的最新的文件放进去,这样可以保持dist下的文件避免有旧文件的情况 -
bable 可以将我们新版本的es转换成低版本的,将浏览器不支持的高版本的新特性转换成浏览器兼容的低版本实现
类
- 通过static 关键字可以定义类属性(静态属性),通过类访问
- readonly 修饰的属性是只读属性
- 方法不需要使用function 修饰,直接方法名+()+{} 就可以了, 如果是static修饰的是类方法
- public 修饰的属性可以在任意位置访问, 属性默认是public的
- private 修饰的属性只能在类内访问, 类外访问会报错,子类也不行, 但如果不修改也可以被访问到,因为ts转换成js的时候会转换成可以访问的
- protected 修饰的属性只能在该类和子类中访问,其他地方不能访问
- 可以通过 用get 修饰来实现get 方法,比如:
class Person {
constructor(name:string) {
this._name = name;
}
private _name:stirng;
get name() { // 注意这里没有下划线, 调用的时候可以直接Person对象.name
return this._name;
}
set name(value: string) {
this._name = name;
}
}
const p = Person()
console.log(p.name); //通过.name调用get方法访问
p.name = "***"; //通过.name调用set方法赋值
- 属性的方便写法
class C{
// 直接将属性定义在构造函数中
constructor(public name:string, public age:number){}
}
// 等同于
class C{
public name:string;
public age:number;
constructor(name:string, age:number){
this.name= name;
this.age = age;
}
}
抽象类
- 用abstract 修饰的类是抽象类,不能用来创建对象,是专门用来被继承的,抽象类中可以添加抽象方法
- 抽象类中使用abstract 修饰的方法,称为抽象方法,抽象方法没有具体的实现,需要继承的子类自己实现,抽象方法只能定义在抽象类中,并且子类必须对抽象方法进行重写
接口
- 接口用来定义类的结构,用来定义一个类中应该包含哪些属性和方法,可以当成类型声明去使用
- 可以定义多个重名的接口, ts会把重名的接口进行合并
- 接口可以在定义类的时候去限制类的结构
- 接口中的所有属性都不能有实际值,也不能有方法的实现, 接口只是定义类的结构
- 接口是让类去实现的, 实现接口就是使类满足接口的要求, 类实现接口使用关键字
implements
;class MyClass implements myInterface { }
- 接口与抽象类的区别是, 抽象类中可以有普通方法也可以有抽象方法, 而接口中只能有抽象方法, 抽象类是被继承的,接口是被实现的
泛型
- 定义函数或是类时,如果遇到类型不明确的就可以使用泛型
- 泛型可以同时指定多个
function fn2<T,K>(a:T, b:K): T{
return a;
}
- 也可以限制泛型的类型,使用extends限定泛型T必须是Inter的实现类或子类, 这里Inter可以是接口也可以是抽象类,或普通类
interface Inter{
length: number;
}
function fn<T extends Inter>(a: T): number{
return a.length;
}
网友评论