其实,之前也学过ts,也在 React16 和 Vue3 的项目中用过,但是,整体功力还不够精湛,没有发挥出ts真正的威力。也因为今年开始,新项目都转战 Vue3,所以后续不管是 Vue 还是 React 的项目,ts 都会是必备搭档。所以用好ts是迫在眉睫了!
之前的学习笔记 TypeScript 入门修炼,在此基础上,更进一步,加深修炼...
思考
其实,Typescript 最核心之一就是 类型!那么类型是什么呢?有很多智者和前辈们已经给我们一语道破:一种思维方式,同时也是错误检查的一柄利器。
一种思维方式:这种类型的思维方式本质就是什么是什么,好比归类,这个是什么类,那个是什么类,在归类的过程中,又衍生什么类...映射到开发中,函数式、面向对象都具有什么方法,什么属性,接着,演化出类似的新方法,类似的新属性等,具备了进化的可能性。那么,类型的思维方式在函数式和面向对象都是高度统一的。(个人简介,欢迎批评指导!)
错误检查的一柄利器:可以在项目开发前期帮助我们提前发现错误,减少程序的错误,让我们的项目更加稳定。
通过思考,我们现有了一定的认知,我们在继续往下飞奔...
TS介绍
2012年微软发布的一门编程语言。发布时就提供了将Typescript翻译到JS的翻译编译器(transcompiler)。
-
Typescript是JS的一个超集。
-
TS同时支持Client Side(浏览器)和Server Side(Nodejs)
-
TS是一个多范式语言(类型帮助函数式和面向对象在设计理念上产生统一,所以同时支持函数式和面向对象,是一种多范式语言)
-
TS同时支持Duck Typing(鸭子类型), Gradual Typing(渐进类型)和Strick Typing(严格类型)
环境配置
其实环境配置还是很重要的,一般都是团队中的leader或者架构师给搭建项目,配置项目之类的。所以要想成长为leader 或者架构师,环境配置是必备技能。
ts-node
Node环境的typescript解释执行器。 REPL(read、evaluate、print、loop)
“读取-求值-输出”循环(英语:Read-Eval-Print Loop,简称REPL),也被称做交互式顶层构件(英语:interactive toplevel),是一个简单的,交互式的编程环境。这个词常常用于指代一个Lisp的交互式开发环境,也能指代命令行的模式。---维基百科
npm i -g ts-node
# yarn global add ts-node
用ts-node执行文件
ts-node demo.ts
配置文件:tsconfig.json
{
"compilerOptions" : {
/// 书写你的配置
}
}
tsc(typescript compiler)
一个ts的编译器。
npm i -g typescript
# yarn global add typescript
可以指定编译某个ts文件:
tsc demo.ts
也可以通过tsconfig.json
配置。
- 可以用
outDir
配置项配置js文件输出的位置 tsc
作为一个指令,可以用--help
查看用法- 可以用
module
指定生成模块的类型
和webpack一起用
初始化一下这个项目:
mkdir ts-webpack
cd ts-webpack
npm init
先安装依赖:
npm install webpack ts-loader typescript webpack-cli --save-dev
# yarn add webpack ts-loader typescript webpack-cli
写一个用于测试的ts文件:
// src/index.ts
export class TreeNode<T> {
left: TreeNode<T>
right: TreeNode<T>
data: T
constructor(data: T) {
this.data = data
}
}
function log(x) {
console.log(x)
}
const node = new TreeNode<number>(100)
log(node.data)
写一个tsconfig.json
文件:
{
}
然后配置一个针对ts文件打包处理的webpack配置。
// webpack.config.js
const path = require('path')
module.exports = {
entry: {
index: "./src/index.ts",
},
mode: "development",
module: {
rules: [
{
test: /\.ts$/,
use: "ts-loader",
exclude: /node_modules/,
},
],
},
resolve: {
extensions: [".tsx", ".ts", ".jsx", ".js"],
},
output: {
filename: "bundle.[name].js",
path: path.resolve(__dirname, "dist"),
}
}
为package.json增加指令:
"scripts": {
"start:dev": "webpack",
...
},
运行起来试一下效果:
npm run start:dev
node ./dist/bundle.index.js
100
React + TS Loader
1、安装npm包
# 先装react依赖
npm i react react-dom --save
npm i @types/react @types/react-dom --save-dev
# yarn add react react-dom
# yarn add -D @types/react @types/react-dom
# 再装个ts-loader和awesome-typescript-loader
npm i ts-loader awesome-typescript-loader --save
# yarn add ts-loader awesome-typescript-loader
# 再装webpack开发用的
npm i webpack-dev-server html-webpack-plugin --save-dev
# yarn add webpack-dev-server html-webpack-plugin -D
- 注意:不装types会报错
- webpack-dev-server 用来启动一个网站
- html-webpack-plugin用于为react程序提供模板
2、编写一个React程序
// src/react.tsx
import React from 'react'
import ReactDOM from 'react-dom'
const App: (() => JSX.Element) = () => {
return <div>
<h1>Hello React!</h1>
</div>
}
ReactDOM.render(<App />, document.getElementById('root'))
因为报错,需要考虑增加 "esModuleInterop": true
和 "jsx": "react"
到tsconfig.json
esModuleInterop: 让TypeScript分别对待CommonJS/AMD/UMD modules,从而让用户获得统一的体验。
jsx选项需要设置成react,这样typescript会将jsx语法转换为React.createClass。
3、编写一个react.html
模板文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
4、编写对应的webpack文件
// webpack.react.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: {
react: "./src/react.tsx",
},
mode: "development",
module: {
rules: [
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/,
},
],
},
resolve: {
extensions: [".tsx", ".ts", ".jsx", ".js"],
},
output: {
filename: "bundle.[name].js",
path: path.resolve(__dirname, "dist"),
},
devServer: {
static: {
directory: path.resolve(__dirname, "dist"),
},
port: 5900,
open: true,
},
plugins: [new HtmlWebpackPlugin({
template: path.resolve(__dirname, "react.html")
})]
}
5、增加package.json脚本
"start:react": "webpack serve --config ./webpack.react.js",
6、尝试执行脚本
npm run start:react
React + Babel
1、补充babel的依赖
npm i babel-loader @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript --save-dev
# yarn add babel-loader @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript
思考:babel-preset VS ts-loader 的区别是什么?
- babel-loader(背后是:babel)
- babel是干什么的? —— The Compiler for next generation Javascript
- 所有编译JS的事情,babel都干!
- es6->es5->es3->polifill
- 缓存+优化
- 插件+生态
- babel是干什么的? —— The Compiler for next generation Javascript
- ts-loader(背后是:typescript)
- ts -> es
2、写一个单独的webpack文件
// webpack.react.addbabel.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: {
"react-babel": "./src/reactbabel.tsx",
},
mode: "development",
module: {
rules: [
{
test: /\.tsx?$/,
use: {
loader: "babel-loader",
options: {
presets: [
'@babel/preset-typescript',
"@babel/preset-react",
"@babel/preset-env"
]
}
},
exclude: /node_modules/,
},
],
},
resolve: {
extensions: [".tsx", ".ts", ".jsx", ".js"],
},
output: {
filename: "bundle.[name].js",
path: path.resolve(__dirname, "dist"),
},
devServer: {
host: '0.0.0.0',
static: {
directory: path.resolve(__dirname, "dist"),
},
port: 5901,
open: true,
},
plugins: [new HtmlWebpackPlugin({
template: path.resolve(__dirname, "react.html")
})]
}
3、增加npm脚本
"start:react-babel": "webpack serve --config ./webpack.react.addbabel.js",
4、尝试一下
npm run start:react-babel
Vue + Loader
1、增加vue需要的依赖
# Vue 的依赖
npm i vue@next --save
npm i -D @vue/compiler-sfc
# yarn add vue@next
# yarn add -D @vue/compiler-sfc
# Vue的loader
npm i vue-loader --save-dev
# yarn add vue-loader -D
sfc - Single File Component
2、写一个Vue的SFC和一个bootstraper
<template>
<h1>TS + Vue!</h1>
</template>
<script lang='ts'>
export default {
setup() {
return {};
},
};
</script>
// main.ts
import {createApp} from 'vue'
import App from './App.vue'
createApp(App).mount("#root")
写完但是App.vue报错,为啥?因为还需要一个shim文件:
// shims-vue.d.ts
/* eslint-disable */
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
shim(垫片),通常为了处理兼容而命名。上面这个shim的目标是让vscode和webpack等知道.vue的文件,可以当做一个组件定义文件来使用。
3、写一个vue的webpack配置
// webpack.vue.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
entry: "./src/main.ts",
mode: "development",
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
options: {
appendTsSuffixTo: [/\.vue$/],
},
exclude: /node_modules/,
},
{
test: /\.vue$/,
loader: 'vue-loader',
}
],
},
resolve: {
extensions: [".vue", ".tsx", ".ts", ".jsx", ".js"],
},
output: {
filename: "bundle.[name].js",
path: path.resolve(__dirname, "dist"),
},
devServer: {
host: '0.0.0.0',
static: {
directory: path.resolve(__dirname, "dist"),
},
port: 5902,
open: true,
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "vue.html"),
}),
new VueLoaderPlugin()
],
}
4、增加npm脚本
"start:vue": "webpack serve --config ./webpack.vue.js",
5、试一试
注意tsconfig中的jsx需要设置为preserve,也就是保留由ts-loader处理。
npm run start:vue
Vue + Babel Preset
1、安装依赖
npm i -D babel-preset-typescript-vue3
# yarn add -D babel-preset-typescript-vue3
2、写一个webpack.config文件
// webpack.vue.addbabel.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
entry: "./src/main.ts",
mode: "development",
module: {
rules: [
{
test: /\.tsx?$/,
use: {
loader: 'babel-loader',
options: {
presets: [
"@babel/preset-env",
// preset-typescript-vue3只增加了typescript的转化能力
"babel-preset-typescript-vue3",
"@babel/preset-typescript",
]
}
},
exclude: /node_modules/,
},
{
test: /\.vue$/,
loader: 'vue-loader',
}
],
},
resolve: {
extensions: [".vue", ".tsx", ".ts", ".jsx", ".js"],
},
output: {
filename: "bundle.[name].js",
path: path.resolve(__dirname, "dist"),
},
devServer: {
host: '0.0.0.0',
static: {
directory: path.resolve(__dirname, "dist"),
},
port: 5903,
open: true,
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "vue.html"),
}),
new VueLoaderPlugin()
],
}
3、配置npm脚本
"start:vue-babel": "webpack serve --config ./webpack.vue.addbabel.js",
4、执行观察结果
npm run start:vue-babel
具体使用
接下来结合这篇整理的笔记学习,TS只学这一篇就够了TS细节知识点修炼更新