TS入门

122 阅读4分钟

1 开发环境搭建

npm i -g typescript
tsc xxx.ts

1.1 webpack配置

  1. 初始化项目

    • 进入项目根目录,执行命令 npm init -y
      • 主要作用:创建package.json文件
  2. 下载构建工具

    • npm i -D webpack webpack-cli webpack-dev-server typescript ts-loader clean-webpack-plugin @babel/core @babel/preset-env babel-loader core-js
      • 共安装了11个包
        • webpack
          • 构建工具webpack
        • webpack-cli
          • webpack的命令行工具
        • webpack-dev-server
          • webpack的开发服务器
        • typescript
          • ts编译器
        • ts-loader
          • ts加载器,用于在webpack中编译ts文件
        • html-webpack-plugin
          • webpack中html插件,用来自动创建html文件
        • clean-webpack-plugin
          • webpack中的清除插件,每次构建都会先清除目录
        • @babel/core
          • babel的核心工具
        • @babel/preset-env
          • babel的预定义环境
        • @babel-loader
          • babel在webpack中的加载器
        • core-js
          • core-js用来使老版本的浏览器支持新版ES语法
  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"]//ts模块化问题解决
          },           
          module: {
               rules: [
                   {
                       test: /.ts$/,
                       use: [
                               {
                                   loader: "babel-loader",
                                   options:{
                                       presets: [
                                           [
                                               "@babel/preset-env",
                                               {
                                                   "targets":{
                                                       "chrome": "58",
                                                       "ie": "11"
                                                   },
                                                   "corejs":"3",
                                                   "useBuiltIns": "usage"//按需加载
                                               }
                                           ]
                                       ]
                                   }
                               },
                               {
                                   loader: "ts-loader",
                               }
                           ],
                       exclude: /node_modules/
                   }
              ]
          },
          plugins: [
              new CleanWebpackPlugin(),
              new HtmlWebpackPlugin({
                  //title:'TS测试'
                  template:'./src/index.html'
              }),
          ]
      
      }
      
  4. 根目录下创建tsconfig.json,配置可以根据自己需要

    • {
          "compilerOptions": {
              "target": "ES2015",
              "module": "ES2015",
              "strict": true
          }
      }
      
  5. 修改package.json添加如下配置

    • {
        ...略...
        "scripts": {
          "test": "echo \"Error: no test specified\" && exit 1",
          "build": "webpack",
          "start": "webpack serve --open chrome.exe"
        },
        ...略...
      }
      
  6. 在src下创建ts文件,并在并命令行执行npm run build对代码进行编译,或者执行npm start来启动开发服务器

1.2 编译选项

  1. 添加tsconfig.json配置文件
  2. 执行tsc -w,自动监视
{  
/*  
tsconfig.json是ts编译器的配置文件,ts编译器可以根据它的信息来对代码进行编译  

  
*/  
"include": [  
    "./src/**/*" //路径:** 表示任意目录  * 表示任意文件   
],  
// "exclude": [  
// "./src/hello/**/*"  //默认值:["node_modules", "bower_components", "jspm_packages"]  
// ]  
  
/*  
compilerOptions 编译器的选项  
*/  
"compilerOptions": {  
    // target 用来指定ts被编译为的ES的版本  
    // 'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'esnext'  
    "target": "es2015",  
    // module 指定要使用的模块化的规范  
    // 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015', 'es2020', 'esnext'  
    "module": "es2015",  
    // lib用来指定项目中要使用的库  
    //'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es  
    //2018', 'es2019', 'es2020', 'esnext', 'dom', 'dom.iterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'scri  
    //pthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.r  
    //eflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.st  
    //ring', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', '  
    //es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2020.bigint', 'es2020.promise', 'es2020.s  
    //haredmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'esnext.array', 'esnext.symbol', 'esnext.asynciterable  
    //', 'esnext.intl', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref'  
    "lib": ["es6", "dom"]  
  
  
    // outDir 用来指定编译后文件所在的目录  
    "outDir": "./dist",  
    // 设置outFile后,所有的全局作用域中的代码会合并到同一个文件中  
    "outFile": "./dist/app.js"  
  
    // 是否对js文件进行编译,默认是false  
    "allowJs": true,  
    // 是否检查js代码是否符合语法规范,默认是false  
    "checkJs": true,  
    // 是否移除注释  
    "removeComments": true,  
    // 不生成编译后的文件  
    "noEmit": false,  
    // 当有错误时不生成编译后的文件  
    "noEmitOnError": true,  
  
    // 所有严格检查的总开关,打开后相当于以下四个配置  
    "strict": true,    
    // 用来设置编译后的文件是否使用严格模式,默认false;es6模块化语法自动开启严格模式  
    "alwaysStrict": true,  
    // 不允许隐式的any类型  
    "noImplicitAny": true,  
    // 不允许不明确类型的this  
    "noImplicitThis": true,  
    // 严格的检查空值  
    "strictNullChecks": true  
    }  
}

2 类型声明

2.1 基本类型

//number
let a: number=10;

//string
let b: string;  
b = 'hello';

//boolean
//let c:boolean = false;  
let c = false;  
c = true;

//字面量
// 直接使用字面量进行类型声明  
let a: 10;  
a = 10;  
// 可以使用 | 来连接多个类型(联合类型)  
let b: "male" | "female";  
b = "male";  
b = "female";  
let c: boolean | string;  
c = true;  
c = 'hello';
let names:(atring|number)[]=[123,'123'];

2.2 any和unknown

//any
let d: any;  
// 声明变量如果不指定类型,则TS解析器会自动判断变量的类型为any (隐式的any)  
let d;  
d = 10;  
d = 'hello';  
d = true;

// unknown 表示未知类型的值  
let e: unknown;  
e = 10;  
e = "hello";  
e = true;  
  
let s:string;  
s = d;// d的类型是any,它可以赋值给任意变量  
  
e = 'hello';  
//s=e;//unknown 实际上就是一个类型安全的any,不能赋值给其他变量
if(typeof e === "string"){  
    s = e; //方式一 
}  
s = e as string;  //方式二
s = <string>e;  //方式三

2.3 void和never

// void 用来表示空,以函数为例,就表示没有返回值的函数,即return;  
function fn(): void{  
}  
  
// never 表示永远不会返回结果,即报错  
function fn2(): never{  
    throw new Error('报错了!');  
}

2.4 对象和枚举

// object表示一个js对象:类型太多了  
let a: object;  
a = {};  
a = function () { };  
   
// 在属性名后边加上?,表示属性是可选的  
let b: {name: string, age?: number};  
b = {name: '孙悟空', age: 18};  
  
let c: {name: string, [propName: string]: any};  
c = {name: '猪八戒', age: 18, gender: '男'};  

//枚举
enum Gender{  
    Male=0,  
    Female=1  
}  
let i: {name: string, gender: Gender};  
i = {  
    name: '孙悟空',  
    gender: Gender.Male // 'male'  
}  
// console.log(i.gender === Gender.Male);

2.5 函数

//先声明后赋值
let d: (a: number ,b: number)=>number;  
d = function (n1: string, n2: string): number{ 
    return 10;  
}

//声明加赋值
function sum(a: number, b: number): number{  
    return a + b;  
}  
let result = sum(123, 456);

//无返回值
function func(item: string): void{ }  

2.6 数组和元组

// string[] 表示字符串数组  
let e: string[];  
e = ['a', 'b', 'c'];  
  
// number[] 表示数值数值  
let f: number[];  
  
let g: Array<number>;  
g = [1, 2, 3];  
  
/*  
* 元组,元组就是固定长度的数组  
* 语法:[类型, 类型, 类型]  
* */  
let h: [string, number];  
h = ['hello', 123];

2.7 符号

// &表示同时  
let j: { name: string } & { age: number };  
// j = {name: '孙悟空', age: 18};  
  
// 类型的别名  
type myType = 1 | 2 | 3 | 4 | 5;  
let k: myType;  
let l: myType;  
let m: myType;  
k = 2;

3 类

3.1 类的继承

// 定义一个Animal类  
abstract class Animal{ //抽象类,只能被继承,不能来创建实例 
    name: string;  
    age: number;  
    constructor(name: string, age: number) {  
        this.name = name;  
        this.age = age;  
    }  
    sayHello(){  
        console.log('动物在叫~');  
    } 
    //abstract:sayHello():void;//抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
}  
  
// 定义一个表示狗的类   
class Dog extends Animal{ 
    sex: number;  
    constructor(name: string, age: number, sex: number) {  
        super(name,age); // 调用父类的构造函数  
        this.sex = sex;  
    }
    run(){//子类方法  
        console.log(`${this.name}在跑~~~`);  
    } 
    sayHello() {//重写父类的方法  
        console.log('汪汪汪汪!');  
    }  
}  
  
// 定义一个表示猫的类  
class Cat extends Animal{  
    sayHello() {//重写父类的方法    
        console.log('喵喵喵喵!');  
    }  
}  
  
const dog = new Dog('旺财', 5);  
const cat = new Cat('咪咪', 3);  
console.log(dog);  
dog.sayHello();  
dog.run();  
console.log(cat);  
cat.sayHello();

3.2 属性的封装

  • public属性
/* class C{  
  
name: string;  
age: number  
  
// 可以直接将属性定义在构造函数中  
constructor(name: string, age: number) {  
this.name = name;  
this.age = age;  
}  
  
}*/  
  
class C{  
    // 可以直接将属性定义在构造函数中:完成属性赋值和声明  
    constructor(public name: string, public age: number) { }  
}  
const c = new C('xxx', 111);  
console.log(c);
  • private属性
//1.private属性
class Person{  
    // TS可以在属性前添加属性的修饰符  
    /*  
    * public 修饰的属性可以在任意位置访问(修改)--默认值  
    * private 私有属性只能在类内部进行访问(修改)  
    *        通过在类中添加方法使得私有属性可以被外部访问  
    * protected 受保护的属性,只能在当前类和当前类的子类中访问(修改),子类的实例访问不到  
    *  
    * */  
    private _name: string;  
    private _age: number;  

    constructor(name: string, age: number) {  
        this._name = name;  
        this._age = age;  
    }  

    /*  
    * getter方法用来读取属性  
    * setter方法用来设置属性  
    * - 它们被称为属性的存取器  
    * */  

    // 定义方法,用来获取name属性  
    // getName(){  
    // return this._name;  
    // }  
    //  
    // // 定义方法,用来设置name属性  
    // setName(value: string){  
    // this._name = value;  
    // }  
    //  
    // getAge(){  
    // return this._age;  
    // }  
    //  
    // setAge(value: number){  
    // // 判断年龄是否合法  
    // if(value >= 0){  
    // this._age = value;  
    // }  
    // }  

    // TS中设置getter方法的方式  
    get name(){  
        // console.log('get name()执行了!!');  
        return this._name;  
    }  
    set name(value){  
        this._name = value;  
    }  

    get age(){  
        return this._age;  
    }  
    set age(value){  
        if(value >= 0){  
            this._age = value  
        }  
    }  
}  
  
const per = new Person('孙悟空', 18);  

//属性可以任意的被修改
// per.setName('猪八戒');  
// per.setAge(-33);  
  
per.name = '猪八戒';  
per.age = -33;  
console.log(per);  
  • protected属性
//2.protected属性
class A{  
    protected num: number;  
    constructor(num: number) {  
        this.num = num;  
    }  
}  
  
class B extends A{  
    test(){  
        console.log(this.num);  
    }  
}  
const b = new B(123);  
// b.num = 33;//不能修改  

4 接口

//1.接口可以当成类型声明去使用:描述一个对象的类型  
type myType = {  
    name: string,  
    age: number  
};  
interface myInterface {
    name: string;  
    age: number;  
}  
interface myInterface {  
    gender: string; //必选属性
    color?:string;//可选属性
    readonly x:number;//只读属性
    [propName:string]:any;//额外的属性检查
}  
const obj: myInterface = {  
    name: 'sss',  
    age: 111,  
    gender: '男'  
}; 
type Person=myType|myInterface
  
//2.用来定义一个类中应该包含哪些属性和方法    
interface myInter{
    name: string;  
    sayHello():void;  
}  
  
class MyClass implements myInter{  
    name: string;  
    constructor(name: string) {  
        this.name = name;  
    }  
    sayHello(){  
        console.log('大家好~~');  
    }  
}

5 泛型

  
/*  
* 在定义函数或是类时,如果遇到类型不明确就可以使用泛型  
*  
* */  
  
function fn<T>(a: T): T{//执行时确定类型:传入和返回的值类型相同  
    return a;  
}   
// 可以直接调用具有泛型的函数  
let result = fn(10); // 不指定泛型,TS可以自动对类型进行推断  
let result2 = fn<string>('hello'); // 指定泛型  
  
// 泛型可以同时指定多个  
function fn2<T, K>(a: T, b: K):T{  
    console.log(b);  
    return a;  
}  
fn2<number, string>(123, 'hello');  

//1.函数
interface Inter{  
    length: number;  
}  
// T extends Inter 表示泛型T必须时Inter实现类(子类)  
function fn3<T extends Inter>(a: T): number{  
    return a.length;  
}  

//2.类
class MyClass<T>{  
    name: T;  
    constructor(name: T) {  
        this.name = name;  
    }  
}  
const mc = new MyClass<string>('孙悟空');

6 keyof和typeof

const todo={
    name:'xiaohong',
    age:18,
    gender:false
}
//keyof返回obj所有key的联合类型
type K=keyof todo;//'name'|  'age' | 'gender'
function prop<T,K extends keyof T>(obj:T,key:K){
    return obj[key]
}
prop(todo,'name')
    
interface IPiont{
    x:number;
    y:number;
}
type Name<T>={ [P in keyof T]:T[P] };
type real=Name<IPiont>;//{x:number,y:number}

//typeof获取一个变量或对象的类型
const sem:IPiont={x:2,y:1}
type sem=typeof sem;//type sem=IPiont

function toArray(x:number):Array<number>{
    return [x]
}
type Func=typeof toArray;//(x:number)=>number[]