1. TypeScript简介
- TS是以JavaScript为基础构建的语言,是一个JavaScript的超集
- TS扩展了JavaScript,并添加了类型
- TS可以在任何支持JavaScript的平台中执行
注意: TS不能被JS解析器直接执行。
需要将TS编写的代码编译成为JS代码,最终执行的时候还是JS代码。
2. 开发环境搭建
- 下载并安装Node.js
- 全局安装typescript
npm i -g typescript - 创建一个ts文件
- 使用tsc对ts文件进行编译
- 进入ts文件所在目录
- 执行命令:tsc xxx.ts
3. 基本类型
3.1 类型声明
通过类型声明可以指定TS变量(参数、形参)的类型。
指定类型后,为变量赋值时,TS编辑器会自动检查值是否符合类型声明,不符合时报错,使得变量只能存储某种类型的值。
语法:
let 变量: 类型;
let 变量: 类型 = 值;
function fn(参数: 类型, 参数: 类型): 类型 {
...
}
虽然执行ts代码时会报错误提示,但还是能成功编译,因为这种写法符合JS的写法。
可以通过配置编译工具,实现出现错误时不生成js文件。
TS可以编译成任意版本的JS,默认编译成ES3。
如果声明变量时不指定类型就进行赋值,TS可以自动对变量进行类型检测。
JS中的函数中不考虑参数的类型和个数。
- 使用 | 运算符连接多个类型(联合类型):
- & 运算符表示同时
3.2 类型
类型 | 例子 | 描述 |
---|
number | 1,-1,1.2 | 任意数字 | string | ‘hello’, ‘’ | 任意字符串 | boolean | 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中新增类型 |
1. 字面量
直接使用字面量进行类型声明:
2. any
any 用于设置任意类型。
- 一个变量设置了 any 相当于对该变量关闭了TS的类型检测(显式的 any):
- 如果不对变量设置类型,TS解析器会自动判断变量的类型为 any(隐式的 any):
使用 TS 时,不建议使用 any 类型,更要避免使用隐式的 any。
3. unknown
unknown 表示未知类型的值。
- 变量类型设置为 unknown 和 any 效果一样:
- 和 any 的区别:
unknown实际就是一个类型安全的any,unknown类型的变量不能直接赋值给其他变量。
如果非要将 b 赋值给 s:
类型断言:告诉编译器 b 的实际类型就是字符串。
变量 as 类型
<类型>变量
4. void
void 用来表示空。
以函数为例,表示没有返回值的函数。
5. never
never 表示永远不会返回结果。
可用于报错:一旦报错程序就立即结束了,就不会返回值。
6. object
object 表示一个js对象。
- {} 用来指定对象中可以包含哪些属性:
- 可选属性:
[propName: string]: any 表示任意类型的属性(propName自己命名的):
- 限制函数的结构:
设置函数结构的类型说明: 语法:(形参: 类型, 形参: 类型) => 返回值
7. array
array 表示一个数组。
语法:
类型[]
Array<类型>
8. tuple
元组,表示固定长度的数组。
语法:[类型, 类型, 类型]
9. enum
枚举。结果是在多个值之间进行选择时可以设置枚举。
10. 类型的别名
4. 编译选项
1. 自动编译文件
当想要一个文件自动编译时:
问题:每次tsc文件发生变化后都要执行tsc xxx.ts 来重新编译。
解决:通过tsc xxx.ts -w 让编译器自动监视文件变化,并应用到最新的文件。
当想要所有文件都自动编译时:
- 在文件夹中创建
tsconfig.js 文件:输入命令行tsc --init - 直接在目标文件夹路径下输入命令行
tsc 即可编译该文件夹下的所有文件 - 输入
tsc -w 可以监视所有 .ts 文件的变化
2. tsconfig.json
tsconfig.json 文件是一个JSON文件,添加配置文件后,只需tsc命令即可完成对整个项目的编译。
一些常用的配置项:
{
"include": [
"./src/**/*"
],
"exclude": [
"./src/hello/**/*",
"node_module"
],
"extends": "./config/base",
"files": [
"core.ts",
"sys.ts",
"xxx.ts"
],
"compilerOptions": {
"target": "ES6",
"module": "es2015",
"lib": [
"es6",
"dom"
],
"outDir": "./dist",
"outFile": "./dist/app.js",
"allowJs": false,
"checkJs": false,
"removeComments": false,
"noEmit": false,
"noEmitOnError": false,
"strict": true,
"alwaysStrict": false,
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
}
}
5. 用webpack打包ts代码
1. 结合webpack和ts完成最基本的开发环境
- 要使用webpack,需要先运行
npm init -y 生成package.json文件来管理项目依赖 - 安装使用webpack所需要的开发依赖
npm i -D webpack webpack-cli typescript ts-loader - 编写webpack配置文件 webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.ts',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
}
}
- 配置tsconfig.json文件
- 在package.json文件中添加配置,可以通过build命令来执行webpack
- 执行
npm run build 对项目进行打包
2. 进阶
2.1 实现webpack自动创建.html文件,并可以根据项目的实际情况来调整该网页引入的资源。
- 执行
npm i -D html-webpack-plugin 命令 - 在webpack.config.js文件中进行配置
const HTMLWebpackPlugin = require('html-webpack-plugin');
module.exports = {
plugins: [
new HTMLWebpackPlugin()
]
}
- 执行
npm run build - 对index.html文件进行配置
或者直接在项目中写一个网页模板,配置之后可以根据模板生成html文件
2.2 实现热更新
- 安装插件
npm i -D webpack-dev-server@3.11.0 - 在package.json文件中添加配置
- 执行
npm start
2.3 让dist文件保持当前最新
- 安装插件
cnpm i -D clean-webpack-plugin 用来清除dist目录 - 在webpack.config.js文件中引入插件
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); - 在plugins数组中进行配置
new CleanWebpackPlugin()
2.4 模块配置
问题:webpack不知道哪些ts文件被作为模块引入,所以打包时会报错 解决:在webpack的resolve中设置引用模块
module.exports = {
resolve: {
extensions: ['.ts', '.js']
}
}
2.5 配置Babel
- 安装插件
cnpm i -D @babel/core @babel/preset-env babel-loader core-js - 修改配置文件
6. 面向对象
1. 类(class)
定义类:
class 类名 {
属性名: 类型;
constructor(参数: 类型) {
this.属性名 = 参数;
}
方法名() {
...
}
}
- 实例属性和静态属性:
class Person {
name: string = '张三';
static age: number = 12
sayHello() {
console.log('hello');
}
static sayHi() {
console.log('Hi');
}
}
const person = new Person();
console.log(Person.age);
person.sayHello();
Person.sayHi();
- 构造函数:
class Dog {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
fn() {
console.log(this);
}
}
const dog1 = new Dog('dog1', 12);
const dog2 = new Dog('dog2', 34);
- 继承
(function () {
class Animal {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
sayHello() {
console.log('hello');
}
}
class Dog extends Animal { }
class Cat extends Animal {
run() {
console.log(`${this.name}在跑`);
}
sayHello() {
console.log('hello');
}
}
const dog = new Dog('dog', 1);
const cat = new Cat('cat', 3);
dog.sayHello();
cat.sayHello();
cat.run();
})()
- super关键字
(function () {
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
sayHello() {
console.log('动物在叫');
}
}
class Dog extends Animal {
age: number;
constructor(name: string, age: number) {
super(name);
this.age = age;
}
sayHello() {
super.sayHello();
}
}
const dog = new Dog('dog', 1);
dog.sayHello();
})();
- 抽象类
(function () {
abstract class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
abstract sayHello(): void;
}
class Dog extends Animal {
sayHello() {
console.log('汪汪汪');
}
}
const dog = new Dog('dog');
dog.sayHello();
class Cat extends Animal {
}
})();
- 接口
(function () {
type myType = {
name: string,
age: number
};
interface myInterface {
name: string;
age: number;
}
interface myInterface {
gender: string;
}
const obj: myInterface = {
name: '张三',
age: 12,
gender: '男'
}
interface myInter {
name: string;
sayHello(): void;
}
class MyClass implements myInter {
name: string;
constructor(name: string) {
this.name = name;
}
sayHello() {
console.log('hello');
}
}
})();
- 属性的封装
(function () {
class Person {
private name: string;
public age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
get name() {
return this.name;
}
set name(value: string) {
this.name = value;
}
}
const per = new Person('张三', 12);
per.age = 34;
console.log(per);
})();
- 泛型
function fn<T>(a: T): T {
return a;
}
fn(a: 10);
fn<string>(a: 'hello');
function fn2<T, K>(a: T, b: K): T {
console.log(b);
return a;
}
fn2<number, string>(a: 123, 'hello');
interface Inter {
length: number;
}
function fn3<T extends Inter>(a: T) {
return a.length;
}
|