1.下载Node.js
64:https://nodejs.org/dist/v14.15.1/node-v14.15.1-x64.msi
32:https://nodejs.org/dist/v14.15,1/node-v14.15.1-x86.msi
npm i -g typescript
创建一个ts文件
执行文件
tsc xxx.ts
类型声明是TS非常重要的一个特点;
通过类型声明可以指定TS中变量(参数、形参)的类型;
指定类型后,当为变量赋值时,TS编译器会自动检查值是否符合类型声明,符合则赋值,否则报错;
简而言之,类型声明给变量设置了类型,使得变量只能存储某种类型的值;语法:
let 变量: 类型;
let 变量: 类型 = 值;
function fn(参数: 类型, 参数: 类型): 类型{
...
}
类型 | 例子 | 描述 |
---|---|---|
number | 1, -33, 2.5 | 任意数字 |
string | ‘hi’, “hi”, hi |
任意字符串 |
boolean | true、false | 布尔值true或false |
字面量 | 其本身 | 限制变量的值就是该字面量的值 |
any | * | 任意类型 |
unknown | * | 类型安全的any |
void | 空值(undefined) | 没有值(或undefined) |
never | 没有值 | 不能是任何值 |
object | {name:‘孙悟空’} | 任意的JS对象 |
array | [1,2,3] | 任意JS数组 |
tuple | [4,5] | 元素,TS新增类型,固定长度数组 |
enum | enum{A, B} | 枚举,TS中新增类型 |
let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;
let big: bigint = 100n;
let isDone: boolean = false
let color: string = "blue"
color = 'red'
let fullName: string = `Bob Bobbington`
let age: number = 37
let sentence: string = `Hello, my name is ${fullName}I'll be ${age + 1} years old next month.`
也可以使用字面量去指定变量的类型,通过字面量可以确定变量的取值范围
let color: 'red' | 'blue' | 'black';
let num: 1 | 2 | 3 | 4 | 5;
// 可以使用 | 连接多个类型(联合类型)
let b: "male" | "female"
b = "male"
b = "female"
// 上边的b只能是 male或者是famale固定值,下边这种方式规定类型更为灵活
let c : boolean | string
c = true
c = "str"
表示任意类型,一个变量设置类型为any后相当于对该变量关闭了Ts的类型检测,不建议使用
// 显示声明为any
let d: any = 4
d = 'hello'
d = true
// 声明变量如果不指定类型,则TS解析器会自动判断变量的类型为any(隐式声明)
let e
e = 10
e = true
// any类型可以赋值给任意变量
let s : stirng
s = d
相当于是一个类型安全的any,unknown类型的变量不能直接赋值给其他变量
let notSure: unknown = 4
notSure = 'hello'
没有返回值
let unusable: void = undefined
function fn() :void{
}
永远不会有返回结果
// 规定函数的返回值是 never,写过kotlin的话看起来就不奇怪了
function error(message: string): never {
throw new Error(message);
}
// object 表示一个js对象
let a : object
a = {}
a = function() {}
// {} 用来指定对象中包含哪些属性
// 语法 : {属性名: 属性值}
// 属性名后边添加 ? 表示属性值可为空
let b : {name: string,age?: number}
b = { name : 'test object'}
console.log(b)
// [propName: string]: any 表示任意类型的属性
let c : {name: string,[propName: string]: any}
c = {name: 'test',age : '18',gender: '男',sal:1000}
let d : (a1:number,a2:number) => number
d = function (n,m){
return n + m
}
let list: number[] = [1, 2, 3]
let list: Array<number> = [1, 2, 3]
元组,相当于是固定长度的数组
let x: [string, number]
x = ["hello", 10];
enum Color {
Red,
Green,
Blue,
}
let c: Color = Color.Green;
enum Color {
Red = 1,
Green,
Blue,
}
let c: Color = Color.Green;
enum Color {
Red = 1,
Green = 2,
Blue = 4,
}
let c: Color = Color.Green
let person: {name:string,gender: 0|1,age:number}
person = {
name: 'eleven',
gender : 1,
age : 16
}
let j : {name:string} & {age :number}
j = {name:'test',age:18}
有些情况下,变量的类型对于我们来说是很明确,但是TS编译器却并不清楚,此时,可以通过类型断言来告诉编译器变量的类型,断言有两种形式:
let someValue: unknown = "this is a string"
let strLength: number = (someValue as string).length
let someValue: unknown = "this is a string"
let strLength: number = (<string>someValue).length
编译文件时,使用 -w 指令后,TS编译器会自动监视文件的变化,并在文件发生变化时对文件进行重新编译。
示例:
tsc xxx.ts -w
如果直接使用tsc指令,则可以自动将当前项目下的所有ts文件编译为js文件。
但是能直接使用tsc命令的前提时,要先在项目根目录下创建一个ts的配置文件 tsconfig.json,tsconfig.json是一个JSON文件,添加配置文件后,只需只需 tsc 命令即可完成对整个项目的编译
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"sourceMap": true
},
"exclude": [
"node_modules"
]
}
添加完成配置文件之后可以使用下列命令对全项目自动编译
tsc -w
选项 | 默认值 | 描述 | 示例 |
---|---|---|---|
include | [“**/*”] | 用来指定哪些文件用来编译 | include":[“src/**/*”, “tests/**/*”] |
exclude | [“node_modules”, “bower_components”, “jspm_packages”] | 定义需要排除在外的目录 | “exclude”: [“./src/hello/**/*”] |
extends | 定义被继承的配置文件 | “extends”: “./configs/base” | |
files | 指定被编译文件的列表,只有需要编译的文件少时才会用到 | “files”: [ “core.ts”, “sys.ts”, “types.ts”, “scanner.ts”, “parser.ts”, “utilities.ts”, “binder.ts”, “checker.ts”, “tsc.ts” ] | |
compilerOptions | 太多了下边讲 |
compilerOptions中包含的选项较多
{
"compilerOptions": {
// target 用来指定ts编译的ES的版本
// ES3(默认)、ES5、ES6/ES2015、ES7/ES2016、ES2017、ES2018、ES2019、ES2020、ESNext
"target": "ES2015",
}
}
{
"compilerOptions": {
// 指定模块化规范
// 'none','commonjs','amd','system','umd','es6','es2015','es2020','esnext'
"module": "ES2015"
}
}
"compilerOptions": {
// 可选值多得一批 ES5、ES6/ES2015、ES7/ES2016、ES2017、ES2018、ES2019、ES2020、ESNext、DOM、WebWorker、ScriptHost ......
"lib": ["ES6", "DOM"]
}
"compilerOptions": {
// 指定编译后的js存放目录
"outDir":"./dist"
}
"compilerOptions": {
//设置outFile之后,默认会将所有的编写在全局作用域中的代码合并为一个js文件,
// 如果module制定了None、System或AMD则会将模块一起合并到文件之中
// 也就是说如果报错了就把module换成上边的三种,建议system
"outFile": "./dist/app.js"
}
"compilerOptions": {
"rootDir": "./src"
}
"compilerOptions": {
"allowJs": false
}
"compilerOptions": {
"checkJs": false
}
"compilerOptions": {
// 不编译ts里边的注释
"removeComments": true
}
noEmit,不生成编译后的文件,默认值是false
noEmitOnError,当发生错误是不编译文件
sourceMap,是否生成sourceMap,默认值:false
下列为阉割检查模式
strict:启用所有的严格检查,默认值为true,设置后相当于开启了所有的严格检查
alwaysStrict: 总是以严格模式对代码进行编译
noImplicitAny: 禁止隐式的any类型
noImplicitThis:禁止类型不明确的this
strictBindCallApply:严格检查bind、call和apply的参数列表
strictFunctionTypes:严格检查函数的类型
strictNullChecks:严格的空值检查
strictPropertyInitialization:严格检查属性是否初始化
额外检查
noFallthroughCasesInSwitch:检查switch语句包含正确的break
noImplicitReturns :检查函数没有隐式的返回值
noUnusedLocals: 检查未使用的局部变量
noUnusedParameters:检查未使用的参数
高级模式
# 创建文件夹
mkdir part3
# 进入文件夹
cd part3
# 使用npm初始化
npm init
# 加载相关依赖 ts-loader用于在webpack中编译ts文件
cnpm i -D webpack webpack-cli typescript ts-loader
创建一个
webpack.config.js
文件
// 引入一个包
const path = require('path')
// webpack中的所有配置信息否应该卸载 module.exports中
module.exports = {
// 指定入口文件
entry:"./src/index.ts",
// 指定打包文件输出的目录
output: {
// 相当于 ./dist
path: path.resolve(__dirname,'dist'),
// 打包后的文件
filename:"bundle.js"
},
// 指定webpack打包是要使用的模块
module:{
// 指定加载的规则
rules: [
{
// test 指定的是规则生效的文件 ,匹配所有以 .ts结尾的文件
test: /\.ts$/,
// 指定loader解析
use: 'ts-loader',
// 指定要派出的文件
exclude: /node-modules/
}
]
}
}
使用webstorm的话直接用它新建的就行了
{
"compilerOptions": {
"module": "ES6",
"target": "ES6",
"sourceMap": false,
"strict": true
},
"exclude": [
"node_modules"
]
}
src
目录下创建index.ts
function sum(firstNum: number,lastNum: number) :number{
return firstNum + lastNum
}
package.json
,添加打包配置{
"name": "part3",
"version": "1.0.0",
"description": "使用webpack整合typescript打包",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
// 在这里添加build参数,使用webpack打包
"build": "webpack"
},
"author": "eleven",
"license": "ISC",
"devDependencies": {
"ts-loader": "^9.4.1",
"typescript": "^4.8.4",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0"
}
}
# 运行打包
npm run build
# 打包之后会出现下列提示信息
> [email protected] build E:\study\code\typescript\part3
> webpack
asset bundle.js 0 bytes [emitted] [minimized] (name: main)
./src/index.ts 15 bytes [built] [code generated]
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value.
Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/
webpack 5.74.0 compiled with 1 warning in 1061 ms
mode
错误,可以修改一下打包参数{
"scripts": {
"build": "webpack --mode production"
}
}
dist/bundle.js
cnpm i -D html-webpack-plugin
webpack.config.js
// 引入html插件
const HTMLWebpackPlugin = require('html-webpack-plugin')
// 在 module.exports 中添加插件
module.exports = {
plugins:[
new HTMLWebpackPlugin()
]
}
cnpm run build
plugins:[
new HTMLWebpackPlugin({
// 这种情况只能指定生成的html的那个title
title: '这是自顶一个的title'
})
]
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Lesscodingtitle>
<link rel="icon" href="https://lesscoding.net/img/icon_2.da28b7db.png">
head>
<body>
body>
html>
webpack.config.js
plugins:[
new HTMLWebpack({
template:'./src/template.html'
})
]
npm install -D webpack-dev-server
package.json
{
"script":{
// 使用chrome打开
// 这里如果提示Cannot GET /chrome 就把chrome.exe删掉
// 如果提示mode xxx 则改成webpack server --open --mode production
"start":"webpack serve --open chrome.exe"
}
}
npm start
clean-webpack-plugin
,打包时删除旧的文件npm i -D clean-wepack-plugin
webpack-config.json
// 引入clean插件
const CLeanWebpackPlugin = require('clean-webpack-plugin')
module.exports = {
plugins:[
new CleanWebpackPlugin()
],
// 用来设置引用的模块
resolve: {
// 解析的后缀
extensions: ['.ts','.js']
}
}
完整配置详见 https://blog.csdn.net/qq_42059717/article/details/127307950 第七章
# 安装@babel/core
# 安装@babel/preset-env 预设浏览器版本
# 安装 babel-loader 加载器
# 安装core-js 兼容不同浏览器js
cnpm i -D @babel/core @babel/preset-env babel-loader core-js
webpack.config.js
,添加相关内容module.exports = {
output: {
// 指定不适用 箭头函数包含,兼容ie浏览器
environment:{
arrowFunction: false
}
},
// 指定webpack打包是要使用的模块
module:{
// 指定加载的规则
rules: [
{
// test 指定的是规则生效的文件 ,匹配所有以 .ts结尾的文件
test: /\.ts$/,
// 将use改为数组 指定loader加载器,从后往前执行
use: [
// 相较于直接写加载器名称,这种配置更为全面
{
//指定加载器
loader:'babel-loader',
// 配置babel
options:{
presets:[
[
//指定环境插件
"@babel/preset-env",
//配置信息
{
// 运行到的浏览器的版本
targets:{
"chrome":"88",
// ie 不支持let const写上这个肯定所有浏览器都可以执行
"ie":"8"
},
// 看 package.json中引入的corejs的大版本
"corejs":"3",
// 使用 corejs 的方法 "usage"表示按需加载
"useBuiltIns":"usage"
}
]
]
}
},
'ts-loader'
],
// 指定要派出的文件
exclude: /node-modules/
}
]
}
}
如果学过java的话这个地方还是比较好理解的,我个人的理解就是将一个事物抽象出来的就是一个对象。如一辆车包含车牌,颜色,发动机,配置,准驾牌照等
// 使用class关键字定义
class Person{
// 实例属性,需要创建对象才可以方位
name: string
// 当然你可以用private对类进行封装
private age: number
// 和java一样静态变量,直接类名调用就行
static gender :string = '男'
// 相当于java中的final
readonly arg1 :string = '只读属性不能改变'
// 相当于java中的常量 static final
// 必须是 static readonly
static readonly arg2 :string = '静态只读属性'
// 全参构造方法
constructor(name:string,age:number) {
this.name = name
this.age = age
}
}
const person = new Person("test",18)
console.log(Person.gender)
这里可以对类进行一下封装,要是有个什么lombok-ts之类的就好了哈哈哈哈
class Person1{
private age: number
private name: string
public getName(): string {
return this.name
}
public setName(name?: string){
this.name = name
}
public getAge(): number{
return this.age
}
public setAge(age?: number){
this.age = age
}
public static sayHello(){
console.log('拜拜啦 ts')
}
}
const p1 = new Person1()
p1.setAge(10)
p1.setName(null)
console.log(p1,'p1')
Person1.sayHello()
class Animal{
name: string
footNumber: number
constructor(name: string,footNumber: number) {
this.name = name
this.footNumber = footNumber
}
say(){}
}
class Dog extends Animal{
say() {
console.log(`我的名字是${this.name},有${this.footNumber}只脚`)
}
}
class Cat extends Animal{
say() {
console.log(`我的名字是${this.name},有${this.footNumber}只脚`)
}
}
let wangcai: Animal = new Dog('旺财', 4)
let zhaocai: Cat = new Cat('招财',4)
wangcai.say()
zhaocai.say()
使用
abstract
定义类,
- 抽象类不能创建示例
- 抽象类可以添加抽象方法
abstract class AnimalTest {
name:string
footer:number
// 定义抽象方法
abstract say()
public eat(){
console.log('吃饭啦')
}
constructor(name: string,footer:number) {
this.name = name
this.footer = footer
}
}
class Chicken extends AnimalTest{
say() {
console.log('咯咯哒')
}
}
let chicken = new Chicken('铁公鸡',2)
console.log(chicken.say())
console.log(chicken.eat())
也是使用interface完成,与type相似,但是type不允许重复定义
接口可以在定义类的时候限制类的结构
(function () {
// 描述一个对象的类型
type myType = {
name: string,
age: number
}
const obj: myType = {
name:'test',
age:500
}
// 接口允许重复定义,会将所有的属性拼接
interface myInterface{
name: string,
age: number,
}
interface myInterface{
gender: string
sayHello()
}
const myInter: myInterface ={
name:'sss',
age:18,
gender:'男',
sayHello() {
console.log('haha')
}
}
// 接口实现类
class MyInterfaceImpl implements myInterface{
age: number;
gender: string;
name: string;
sayHello() {
}
}
})
私有化属性,公共方法
这种方式需要写get set比较费劲
class Person1{
private age: number
private name: string
public getName(): string {
return this.name
}
public setName(name?: string){
this.name = name
}
public getAge(): number{
return this.age
}
public setAge(age?: number){
this.age = age
}
public static sayHello(){
console.log('拜拜啦 ts')
}
}
const p1 = new Person1()
p1.setAge(10)
p1.setName(null)
console.log(p1,'p1')
Person1.sayHello()
class Person{
name: string
get name(): string{
return this.name
}
set name(name: string){
this.name = name
}
}
console.log
function fn(a: any): any {
return a
}
function fnT<T> (a: T): T{
return a
}
// 不指定类型 js自动推断
let result = fnT(10)
// 指定泛型
let result2 = fnT<string>('-10')
//反省可以同时指定多个
function fn2<T,K>(a: T,b:K):T{
return a
}
fn2<number,string>(2,'2')
interface Interface {
length: number
}
// 指定泛型的父类,只要是父类或者是其子类就行
function fn3<T extends Interface>(a: T):number {
return a.length
}
class MyClass<T> {
age: T
constructor(age: T) {
this.age = age
}
}
创建一个新的文件夹,将上边的
package.json
、tsconfig.json
,webpack.config.js
复制过来
# 添加相关依赖
npm i -D less less-loader css-loader style-loader
module:{
// 指定加载的规则
rules: [
// 设置支持 less文件处理
{
test: /\.less$/,
use:[
'style-loader',
'css-loader',
'less-loader'
]
}
]
}
# 添加相关依赖
npm i -D postcss postcss-loader postcss-preset-env
module:{
// 指定加载的规则
rules: [
// 设置支持 less文件处理
{
test: /\.less$/,
use:[
'style-loader',
'css-loader',
// postcss
{
loader: 'postcss-loader',
options: {
postcssOptions:{
plugins: [
[
"postcss-preset-env",
{
// 兼容每个浏览器的最新的两个版本
browsers:'last 2 version'
}
]
]
}
}
},
'less-loader'
]
}
]
}
'less-loader'
]
}
]
}
## 2. 添加css老版本支持
- 添加npm依赖
```shell
# 添加相关依赖
npm i -D postcss postcss-loader postcss-preset-env
module:{
// 指定加载的规则
rules: [
// 设置支持 less文件处理
{
test: /\.less$/,
use:[
'style-loader',
'css-loader',
// postcss
{
loader: 'postcss-loader',
options: {
postcssOptions:{
plugins: [
[
"postcss-preset-env",
{
// 兼容每个浏览器的最新的两个版本
browsers:'last 2 version'
}
]
]
}
}
},
'less-loader'
]
}
]
}