从0到1构建TypeScript项目以及初学TypeScript(day01)

静态强类型语言与动态弱类型语言

  • 静态强类型语言
    • 对类型极度严格
    • 及时发现错误
    • 运行时性能好
    • 自文档化
  • 动态弱类型语言
    • 对类型非常放松
    • Bug发现不及时(可单元测试发现)
    • 运行时性能差(可通过引擎改善)
    • 可读性差 (文档可以通过工具生成)
    • 更具灵活性

构建TypeScript项目

预装软件 : nodeJs & VSCode

体验typescript

  • 新建文件夹 ts_in_action
  • 执行 npm init -y 初始化项目
  • 执行 npm i typescript -g 安装ts
  • 执行 tsc --init 创建ts配置项( tsc -h 查看帮助信息)

此时目录结构
目录结构

  • 新建 src 目录
  • 在src目录下创建 index.ts
    // index.ts
    let hello : string = 'Hello World!'
    
  • 执行 tsc ./src/index.ts 编译 index.ts 文件
  • 此时同目录下生成了 index.js 文件
    // index.js
    var hello = 'Hello World!';
    // :string 类型注解
    

配置typescript

  • 安装构建工具 npm i webpack webpack-cli webpack-dev-server -D

  • ts_in_action下,新建 build 目录

  • 拷贝四个配置文件

    • webpack.base.config.js
      // 公共环境的配置
      
      const HtmlWebpackPlugin = require('html-webpack-plugin');
      
      module.exports = {
        // 指定入口文件
        entry: './src/index.ts',
        output: {
          // 输出文件名,输出目录默认disk
          filename: 'app.js',
        },
        resolve: {
          // 指定扩展名
          extensions: ['.js', '.ts', '.tsx'],
        },
        module: {
          rules: [
            {
              // 安装ts-loader : npm i ts-loader typescript -D
              // ts-loader正则,以ts或tsx结尾的文件
              test: /\.tsx?$/i,
              use: [{
                loader: 'ts-loader',
              }],
              // 排除
              exclude: /node_modules/,
            },
          ],
        },
        plugins: [
          // 插件,通过模板生成网站首页,把输入文件嵌入,需要安装
          // npm i html-webpack-plugin -D
          new HtmlWebpackPlugin({
            template: './src/tpl/index.html',
          }),
        ],
      };
      
    • webpack.config.js
      // 所有配置文件的入口
      
      // npm i webpack-merge -D
      // const merge = require('webpack-merge'); 失效,替换如下
      var { merge } = require('webpack-merge');
      
      //引入其他配置文件
      const baseConfig = require('./webpack.base.config');
      const devConfig = require('./webpack.dev.config');
      const proConfig = require('./webpack.pro.config');
      
      // 判断当前环境变量
      let config = process.NODE_ENV === 'development' ? devConfig : proConfig;
      
      // 合并
      module.exports = merge(baseConfig, config);
      
    • webpack.dev.config.js
      // 开发环境的配置
      module.exports = {
        devtool: 'cheap-module-eval-source-map',
      };
      
    • webpack.pro.config.js
      // 生产环境的配置
      
      // npm i clean-webpack-plugin -D
      // 每次成功构建后,清空disk目录,避免缓存的无用文件
      
      const { CleanWebpackPlugin } = require('clean-webpack-plugin');
      
      module.exports = {
        plugins: [
          new CleanWebpackPlugin(),
        ],
      };
      
  • 执行 npm i ts-loader typescript -D 安装ts-loader,并再次本地安装typescript

  • 执行 npm i html-webpack-plugin -D 安装插件,通过模板生成网站首页,把输入文件嵌入

  • 编写模版文件,在src目录下创建 tpl 目录,再创建 index.html 文件

    <!-- index.html -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>hello ts</title>
    </head>
    <body>
        <div class="app"></div>
    </body>
    </html>
    
  • 执行 npm i clean-webpack-plugin -D ,每次成功构建后,清空disk目录,避免缓存的无用文件

  • 执行 npm i webpack-merge -D 安装webpack-merge

  • 打开package.json

    • 修改入口文件
      "main": "./src/index.ts",
      
    • 编写启动开发环境的命令
      "scripts": {
          "start": "webpack-dev-server --mode=development --config ./build/webpack.config.js",
          "test": "echo \"Error: no test specified\" && exit 1"
        },
      
  • 执行npm start

  • 在浏览器输入 localhost:8080

  • 在这里插入图片描述

将index.ts中字符串插入到页面中

  • 编写index.ts

    let hello : string = 'Hello World!'
    document.querySelectorAll('.app')[0].innerHTML = hello;
    

在这里插入图片描述

构建生产环境的脚本

  • 在package.json中修改

    "scripts": {
        "start": "webpack-dev-server --mode=development --config ./build/webpack.config.js",
        "build": "webpack --mode=production --config ./build/webpack.config.js",
        "test": "echo \"Error: no test specified\" && exit 1"
      },
    
  • 执行 npm run build

  • 此时目录结构
    在这里插入图片描述

typescript的数据类型

  • ES6的数据类型
    • Boolean
    • number
    • string
    • array
    • function
    • object
    • symbol
    • undefined
    • null
  • typescript的数据类型(完全覆盖ES6)
    • Boolean
    • number
    • string
    • array
    • function
    • object
    • symbol
    • undefined
    • null
    • void
    • any
    • never
    • 元组
    • 枚举
    • 高级类型

类型注解

  • 作用: 相当于强类型语言中的类型声明
  • 语法: (变量/函数):type

回到工程中

  • 在src下新建 datatype.ts

    // 原始类型
    let bool: boolean = true
    let num: number = 123
    let str: string = 'abc'
    
    // str = 123  //报错,数据类型不可以改变
    
    // 数组
    let arr1: number[] = [1, 2, 3]
    let arr2: Array<number> = [1, 2, 3]
    // 联合类型
    let arr3: Array<number | string> = [1, 2, 3, '4']
    
    // 元组 特殊数组 限定元素类型和个数
    let tuple1: [number, string] = [0, '1']
    tuple1.push(2) // 不报错,允许添加新元素,不建议这样使用
    // tuple1[2]      // 报错,不允许访问
    
    // let tuple2: [number, string] = [1, '1']      //报错
    // let tuple2: [number, string] = [0, '1', 1]   //报错
    
    // 函数
    let add1 = (x: number, y: number): number => x + y
    let add2 = (x: number, y: number) => x + y  //省略函数返回类型,ts具有类型推断功能
    let compute: (x: number, y:number) => number //函数类型,没有具体实现
    compute = (a, b) => a + b;     //实现函数类型
    
    // 对象
    let obj1: object = {x: 1, y: 2}
    // obj1.x = 3  //报错,不允许
    let obj2: {x: number, y: number} = {x: 1, y: 2}
    obj2.x = 3
    
    // symbol 具有唯一的值
    let s1: symbol = Symbol()
    let s2 = Symbol()
    console.log(s1 === s2)  //false
    
    // undefined, null  只能赋值为本身
    let un: undefined = undefined
    let nu: null = null
    // 在tsconfig.js中设置"strictNullChecks": false 或 使用联合类型   允许↓
    // num = undefined
    // num = null
    
    // void
    let noReturn = () => {}
    
    // any 除特殊情况不建议使用
    let x
    x = 1
    x = []
    x = ''
    x = () => {}
    
    // never
    let error = () =>{
        throw new Error('error')
    }
    let endless = () =>{
        while(true){}
    }
    
  • 在index.js中引入

    import './datatype'
    

typescript枚举类型

使用枚举类型可以提高程序可读性,以不变应万变。

  • 枚举: 一组有名字的常量集合

    • 例如手机中的通讯录 姓名+号码
  • 在src下新建 enum.ts

    // 数字枚举
    enum Role {
        Reporter,
        Developer,
        Maintainer = 10,
        Owner,
        Guest
    }
    // 既可以用过名字索引,又可以通过值索引(反向映射)
    console.log(Role.Reporter)      //0
    console.log(Role.Developer)     //1
    console.log(Role.Maintainer)    //10
    console.log(Role.Developer)     //11
    
    // 字符串枚举 名称索引
    enum Message {
        Success = '成功',
        Fail = '失败'
    }
    
    // 异构枚举 不建议使用
    enum Answer {
        N,
        Y = 'yes'
    }
    
    // 枚举成员 性质
    // Role.Reporter = 2  //报错,只读,不可修改
    enum Char {
        // const
        a,
        b = Char.a,
        c = 1 + 3,      //会在编译时计算出结果
        // computed 需要计算的枚举成员,不会再编译阶段进行计算,运行时计算
        d = Math.random(),
        e = '123'.length,
        // f       //在computed后的成员需要被赋值
    }
    
    // 常量枚举  会在编译时被移除 当不需要对象而需要对象的值的时候可以使用
    const enum Month{
        Jan,
        Feb,
        Mar
    } 
    let month = [Month.Jan, Month.Feb, Month.Mar]   //此时常量枚举会被替换为常量
    
    // 枚举类型
    enum E {a, b}
    enum F {a = 0, b = 1}
    enum G {a = 'apple', b = 'banana'}
    
    let e: E = 3
    let f: F = 3
    // e === f //报错,不允许不同类型进行比较
    
    let e1: E.a = 1
    let e2: E.b
    // e1 === e1 //报错
    let e3: E.a = 1
    e1 === e3 
    
    let g1: G = G.b
    let g2: G.a = G.a
    
    

typescript重要概念:接口

接口可以用来约束对象、函数、类的结构和类型。
代码协作的契约,不可改变。

对象类型接口

  • 在src下新建 interface.ts

    // interface.ts 对象类型接口
    
    
    interface List {
        //成员
        readonly id: number;    // readonly 只读属性
        name: string;
        // [x: string]: any;  //字符串索引签名,用任意字符串去索引List,可以得到任意结果
        age?: number        // ? 可选属性
    }
    
    interface Result {
        //成员的取值为 List数组
        data: List[]
    }
    
    // 渲染函数
    function render(result: Result){
        // 遍历 List
        result.data.forEach((value) => {
            //打印 List中的 id, name
            console.log(value.id, value.name)
    
            //新需求
            if(value.age){
                console.log(value.age)
            }
            // value.id++      //只读属性不允许修改
    
        })
    }
    
    // 假设从后端接收到的数据
    let result = {
        data: [
            {id:1, name: 'A', sex: 'male'},     //允许字段超出定义,满足必要条件即可 
            {id:2, name: 'B'}
        ]
    }
    
    render(result)
    
    // 如果直接传入字面量,ts会对额外字段进行类型检查
    render(
        {
            data: [
                {id:1, name: 'A', sex: 'male'},     
                {id:2, name: 'B'},
                {id:3, name: 'B', age: 10}
            ]
        } as Result     //使用  类型断言/字符串索引签名  绕过类型检查
    )
    
    
    // 用数字索引的接口
    interface StringArray {
        [index: number]: string  //用任意数字索引StringArray,都会得到stirng
    }
    let chars: StringArray = ['A', 'B']
    
    interface Names {
        [x: string]: string,     //用任意字符串去索引Names,都会得到string
        // y: number        //不允许
        [z: number]: string ,
        // [a: number]: number      // 不允许,与string不兼容 
    }
    
    

函数类型接口

  • 在 interface.ts 中追加

    // interface.ts 函数类型接口
    
    
    let add3: (x: number, y: number) => number
    
    // 定义函数类型接口
    interface Add1 {
        (x: number, y: number): number
    }
    
    // 使用类型别名 为函数起一个名字
    type Add2 = (x: number, y: number) => number
    // 实现具体函数
    let add4: Add2 = (a, b) => a + b
    
    // 混合类型接口 既可以定义函数,有可以有属性或者方法
    interface Lib {
        //函数
        (): void;
        //属性
        version: string;
        //方法
        doSomething(): void;
    }
    //实现接口  封装到方法,可以创建多个实例
    function getLib(){
        let lib: Lib = ( () => {} ) as Lib;  //使用类型断言,因为我们明确知道lib就是我们需要的
        lib.version = '1.0';
        lib.doSomething = () => {}
        return lib;
    }
    
    let lib1 = getLib();
    lib1();
    lib1.doSomething();
    lib1.version;
    
    let lib2 = getLib();
    
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值