一:编译选项
自动编译文件
编译文件时,使用-w指令,TS编译器会自动监视文件变化,在文件发生变化时,对文件进行重新编译。
tsc xxx.ts -w
自动编译整个项目
如果直接使用tsc或者tsc -w ,则可以自动将对当前项目下的所有ts文件编译成js文件
但是能直接使用tsc命令时,要先在项目根目录下创建tsconfig.json配置文件
tsconfig.json配置项
include:只编译那些目录下的文件
// include:只编译那些目录下的文件
// 默认值 ["**/*"]
"include": ["test/**/*","src/**/*"]//表示只编译test和src文件下的ts文件
exclude:那些目录下的文件不会被编译
// exclude:那些目录下的文件不会被编译
// 默认值 ["node_modules", "bower_components", "jspm_packages"]
"exclude":["dist/**/*"] //dist目录下的文件不会被自动编译
extends:定义被继承的配置文件
"extends":"./base.json"
files:只编译那些文件,具体的文件
"files": [
"./test/test.ts"
]
compilerOptions:包含多个配置子项
"compilerOptions": {
//编译后代码使用的模块化系统
"module": "CommonJS",
// 编译目标js版本
"target":"ES6",
//指定代码运行时所包含的库(宿主环境)
"lib":["ES6","DOM"],
//编译后js所在的目录
"outDir": "dist",//编译后js文件会生成在dist目录
//将所有ts文件集中编译到一个js文件
"outFile": "dist/app.js",
//指定代码的根目录
"rootDir": "./src",
// 是否对js文件编译
"allowJs": true,
//是否对js文件进行检查
"checkJs": true,
//是否删除注释
"removeComments":false,
// 不对代码进行编译
"noEmit": false,
//是否生成sourecMap
"sourceMap": false
}
严格检查
-
strict
- 启用所有的严格检查,默认值为true,设置后相当于开启了所有的严格检查
-
alwaysStrict
- 总是以严格模式对代码进行编译
-
noImplicitAny
- 禁止隐式的any类型
-
noImplicitThis
- 禁止类型不明确的this
-
strictBindCallApply
- 严格检查bind、call和apply的参数列表
-
strictFunctionTypes
- 严格检查函数的类型
-
strictNullChecks
- 严格的空值检查
-
strictPropertyInitialization
- 严格检查属性是否初始化
-
额外检查
-
noFallthroughCasesInSwitch
- 检查switch语句包含正确的break
-
noImplicitReturns
- 检查函数没有隐式的返回值
-
noUnusedLocals
- 检查未使用的局部变量
-
noUnusedParameters
- 检查未使用的参数
-
-
高级
-
allowUnreachableCode
-
检查不可达代码
-
可选值:
- true,忽略不可达代码
- false,不可达代码将引起错误
-
-
noEmitOnError
- 有错误的情况下不进行编译
- 默认值:false
-
二:webpack
实际开发中我们都需要使用构建工具对代码进行打包,TS同样也可以结合构建工具一起使用,下边以webpack为例介绍一下如何结合构建工具使用TS。
步骤:
1.初始化项目
进入项目根目录,执行 npm init -y,创建package.json
2.下载构建工具
命令:npm i -D webpack webpack-cli webpack-dev-server typescript ts-loader clean-webpack-plugin
共7个包 webpack :构建工具webpack
webpack-cli :webpack的命令工具
webpack-dev-serve : webpack的开发服务器
typescript : ts编译器
ts-loader : ts加载器,在webpack中编译ts文件
html-webpack-plugin :webpack中html插件,用来自动创建html文件
clean-webpack-pluhin :webpack中的清除插件,每次构建都会先清洗目录
3.根目录下创建webpack的配置文件webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
optimization:{
minimize: false // 关闭代码压缩,可选
},
entry: "./src/index.ts",
devtool: "inline-source-map",
devServer: {
contentBase: './dist'
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js",
environment: {
arrowFunction: false // 关闭webpack的箭头函数,可选
}
},
resolve: {
extensions: [".ts", ".js"]
},
module: {
rules: [
{ test: /\.ts$/, use: { loader: "ts-loader" }, exclude: /node_modules/ } ] }, plugins: [ new CleanWebpackPlugin(), new HtmlWebpackPlugin({ title:'TS测试' }), ] }
三:面向对象
1:类
定义属性和方法 属性分为静态属性和实例属性 区别就在于静态方法只有类可以调用,而实例属性只有类的实例对象可以调用
同理方法也分为实例方法和静态方法
class Fthan{
// 实例属性
name:string='fthanClass';
// 静态属性,用关键字static定义静态属性(类属性)
static age:number=24;
// 定义实例方法
getdata(){
console.log("holle");
}
// 定义静态方法
static getdataA(){
console.log("holle A");
}
}
var ft=new Fthan()
// 实例属性只能通过实例访问,ft就是Fthan类的实例
console.log(ft.name);
//静态属性只能通过类来访问
console.log(Fthan.age);
// 调用实例方法
ft.getdata()
// 调用类方法
Fthan.getdataA()
构造函数和this
class Fthan{
name:string;
age:number;
//构造函数constructor,在new时此构造函数就会被执行
constructor(x:string,y:number){
// 这里的this就是当前的类
// 可以通过this向新建的对象中属性然后赋值
console.log(this);
this.name=x;
this.age=y;
}
asd(){
// 实例方法中的this指向的是该方法的调用者。
console.log(this);
}
}
var ft=new Fthan('tsy',24);
var a=new Fthan('cjy',23)
ft.asd();
关键字
readonly:只读
class Fthan{
// readonly关键字修饰的属性是只读的不可修改的
readonly name:string;
age:number;
constructor(x:string,y:number){
this.name=x;
this.age=y;
}
}
var ft=new Fthan('tsy',24);
// 因为在name属性前添加了readonly关键字,所以name不可修改
ft.name='lll' //报错,无法更改值
继承extends 子类继承父类采用就近原则,如果要访问或者调用的方法子类中存在,则直接访问子类中的属性或者方法。
class Father{
name:string
constructor(name:string){
this.name=name
}
asd(){
console.log('lllll');
}
}
class Son extends Father{
age:number=18;
}
let a=new Son('tsy');
console.log(a);
a.asd()
// 结果{name: 'tsy', age: 18}
// lllll
super 如果子类中存在constructor,那么子类的constructor中必须使用super继承父类中的constructor
class Father{
name:string
constructor(name:string){
this.name=name
}
asd(){
console.log('我是父类');
}
}
class Son extends Father{
age:number;
constructor(name:string,age:number){
super(name);
this.age=age;
}
asd(){
//super在子类中就表示父类的实例
//在子类方法中通过super调用父类在被重写的方法
super.asd()
}
}
let a=new Son('tsy',23);
// 结果{name: 'tsy', age: 23}
a.asd()
// 结果 “我是父类”
public,protected,private修饰符
public:(默认) 在实例对象,子类,本身类中可更改
class Father{
public name:string
constructor(name:string){
this.name='ppp'//自身中可更改
}
}
class Son extends Father{
constructor(name:string){
super(name);
this.name='asd'//子类中可更改
}
}
let a=new Son('tsy');
a.name='qwe'//实例对象中可更改
// 结果 {name: 'qwe'}
protected:子类,本身类中可更改
class Father{
protected name:string
constructor(name:string){
this.name='ppp'//自身中可更改
}
}
class Son extends Father{
constructor(name:string){
super(name);
this.name='asd'//子类中可更改
}
}
let a=new Son('tsy');
a.name='qwe'//不可更改
private:本身类中可更改
class Father{
private name:string
constructor(name:string){
this.name='ppp'//自身中可更改
}
}
class Son extends Father{
constructor(name:string){
super(name);
this.name='asd'//子类中不可更改
}
}
let a=new Son('tsy');
a.name='qwe'//不可更改
属性存取器
对于一些不希望被任意修改的属性,可以将其设置为private 属性设置为private,则改该属性则无法被外界访问或者修改 怎样通过外界访问或进行赋值修改呢?
方法:读取属性的方法叫做setter方法,设置属性的方法叫做getter方法
class Father{
private _name:string;
constructor(name:string){
this._name=name
}
get name(){
return this._name
}
set name(name:string){
this._name=name
}
}
let a=new Father('tsy');
a.name='asd'//触发setter
console.log(a.name); //触发getter
console.log(a);
//打印结果{_name: 'asd'}
抽象类
关键字abstract
什么是抽象类,抽象类和其他类差不多,但是抽象类是不可被new的
说白了,抽象类的出现就是为了给其他类继承的爸爸类
此外抽象类还有一个抽象方法
abstract class Fthan{
name:string;
constructor(name){
this.name
}
// 抽象方法
// 使用abstract关键字。切没有返回值
// 抽象方法的意义就是为了,子类必须对其重写
abstract getdata():string;
abstract setdata():void;
}
class Son extends Fthan{
getdata(){
return '重写的方法'
}
setdata(){
console.log('重写的方法');
}
}
接口
关键字:interface 接口和抽象类很相似,接口中的所有属性和方法都是抽象的,没用具体的值。接口主要负责定义一个类的结构,限制一个对象的结构。
interface Person{
name:string;
fun():void;
}
// 定义一个类的结构
class Son implements Person{
name='';
constructor(name:string){
this.name=name
};
fun(){
console.log('lll');
}
}
let obj1=new Son('tsy')
// 限制一个对象的内部结构
let obj:Person = {
name:'tsy',
fun:()=>{
console.log(';;;');
}
}
obj.fun()
只读 关键字 readonly
只有在对象刚刚被创建的时候给其赋值
interface Person{
name:string;
readonly age:number;
}
let obj:Person = {
name:'sty',
age:24
}
obj.age=25 //error
任意/可选
interface Person{
name:string;
age?:number;
[arr1:string]:any;
}
let obj:Person={
name:'tsy',
}
let obj1:Person={
name:'tsy',
age:24
}
let obj2:Person={
name:'tsy',
sex:'男'
}
接口和类型别名的区别
接口
interface Person{
name:string;
age:numder;
};
interface Son{
(x:number): void;
};
类型别名
type Tsy={
name:string,
age:number
};
type Fun = (x:string)=>void;
泛型
在定义函数或者是类时,如果遇到类型不明确就可以使用泛型
function fn<T>(a:T):T{
return a;
}
let res=fn(10);//不指定泛型,TS可以对类型进行推断
let res2=fn<string>('sss'); //指定泛型
//泛型可同时指定多个
function fn2<T,K>(a:T,b:K):T{
console.log(b);
return a;
}
fn2<string,number>('123',1);
//T extends Inter 表示泛型T必须是Inter的实现类(子类)
interface Inter{
length:number
}
function fn3<T extends Inter>(a:T):number{
return a.length;
}
console.log(fn3({length:10}));
//类也可以使用泛型
class MyClass<T>{
name:T;
constructor(name:T){
this.name=name;
}
}
const mc=new MyClass<string>('tsy')