预装软件 : nodeJs & VSCode
// index.ts
let hello : string = 'Hello World!'
// index.js
var hello = 'Hello World!';
// :string 类型注解
安装构建工具 npm i webpack webpack-cli webpack-dev-server -D
ts_in_action下,新建 build 目录
拷贝四个配置文件
// 公共环境的配置
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',
}),
],
};
// 所有配置文件的入口
// 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);
// 开发环境的配置
module.exports = {
devtool: 'cheap-module-eval-source-map',
};
// 生产环境的配置
// 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 文件
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>hello tstitle>
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
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
在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'
使用枚举类型可以提高程序可读性,以不变应万变。
枚举: 一组有名字的常量集合
在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
接口可以用来约束对象、函数、类的结构和类型。
代码协作的契约,不可改变。
在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();