TypeScript入门基础

Posted 前端More

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TypeScript入门基础相关的知识,希望对你有一定的参考价值。

文章目录

1 TypeScript介绍

1.1 什么是TypeScript?

TypeScript简称TS,它是以javascript为基础构建的语言,是JavaScript的超集(TS是JS的升级版),本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。 TS的目的是为了更安全高效的类型提示和检查

1.2 为什么需要 TypeScript

JavaScript是弱类型语言,很多错误只有在运行时才会被发现,而TypeScript提供了一套静态检测机制,可以帮助我们在编译时就发现错误 。

1.3 JS与TS的相关知识

JS是一门标准的弱类型且动态类型的语言,所以JS灵活多变,缺失类型系统的可靠性。

TS是一门标准的强类型且静态类型的语言。

强类型VS弱类型

强类型:在语言层面就限制了函数的实参类型必须与形参类型相同

弱类型:语言层面不会限制实参的类型; 我们定义一个变量,不需要考虑它的类型

形参相当于函数中定义的变量,实参是在运行时的函数调用时传入的参数。

强类型语言的特点就是不允许程序在发生错误后继续执行

弱类型的一个特点就是在计算时,不同类型之间对使用者透明地对变量进行隐式转换。

相较于弱类型语言,强类型有着明显的优势

  • 错误更早暴露(编码阶段就能发现并避免类型异常);
  • 代码更智能,编码更准确(编辑器时时刻刻都知道变量的类型,作出提示);
  • 重构更牢靠(重构时,能及时暴露出相关代码异常信息,可及时准确的对耦合代码进行修改);
  • 减少不必要的类型判断(在编码阶段,参数类型已经确定,就不用再对类型做约定判断);

静态类型VS动态类型

静态类型语言:一个变量在声明时它的类型就是明确的,声明过后,它的类型就不可修改;

动态类型语言:在代码运行阶段才能明确变量的类型,而且变量的类型随时可以改变;

两者区别:是否允许随时修改变量的类型 ,

如何区分:一门语言在编译时报错,那么是静态类型,如果在运行时报错,那么是动态类型。

静态类型的好处:有利于代码的重构,可以在编译器编译时捕获错误。这样我们在编写代码的时候就能避免很多错误,提高编码的效率!

静态类型语言动态类型语言
对类型极度严格对类型非常宽松
立即发现错误不能立即发现(单元测试)
运行时性能好运行时性能差
自文档化可读性差(工具生成文档)

1.4 TypeScript特性

  • 支持最新的JavaScript新特性(ES6-ES12),添加ES不具备的新特性
  • 支持代码静态检查,拥有了更加严格的语法和更强大的功能 ,TS可以在代码执行前就完成代码的检查,
    减小了运行时异常的出现的几率;
  • 同样的功能,TS的代码量要大于JS,但由于TS的代码结构更加清晰,变量类型更加明确,在后期代码的维护中TS却远远胜于JS;
  • 支持诸如C,C++,Java,Go等后端语言中的特性 (枚举、泛型、类型转换、命名空间、声明文件、类、接口等) ,有强大的开发工具以及丰富的配置选项。

1.5 TypeScript安装

安装Node:https://nodejs.org/zh-cn/

安装ts

 npm i -g typescript 

将ts文件编译为js文件(生成一个和ts文件名称相同的js文件),然后执行js文件

//编译ts文件
tsc XXX.ts
//运行js文件
node XXX.js

也可以安装ts-node直接运行ts文件 ,不需要编译为js

 /安装ts-node
npm i -g ts-node 
//直接运行ts文件
ts-node XXX.ts

2 TypeScript的基本类型

2.1 类型声明

类型声明给变量设置了类型,使得变量只能存储某种类型的值。

通过类型声明可以指定TS中变量(参数字、形参)的类型,指定类型后,当为变量赋值时,TS编译器会自动检查值是否符合类型声明,符合则赋值,否则报错。

语法如下:

// 声明一个变量
let 变量: 类型;

// 声明一个变量并给其赋值
let 变量: 类型 =;

// 声明一个函数
function fn(参数: 类型, 参数: 类型): 函数返回值类型
    ...

// a 的类型设置为了number,在以后的使用过程中a的值只能是数字
let a: number;
a = 10;
a = 33;
a = 'hello'; // 此行代码会报错,因为变量a的类型是number,不能赋值字符串

自动类型判断:TS拥有自动的类型判断机制,当对变量的声明和赋值是同时进行的,TS编译器会自动判断变量的类型,所以变量的声明和赋值时同时进行可以省略掉类型声明。

:虽然可以省略类型,但声明类型对定义函数有极大的提升

let a = 1;
a = 'sj';//报错 不能将类型'string'分配给类型'number'

2.2 类型分类

类型例子描述
number1, -33, 2.5任意数字
string‘hi’, “hi”,模板字符串``任意字符串
booleantrue、false布尔值true或false
字面量其本身限制变量的值就是该字面量的值
any*任意类型
unknown*类型安全的any
void空值(undefined)没有值(或undefined)
never没有值不能是任何值
objectname:‘孙悟空’任意的JS对象
array[1,2,3]任意JS数组
tuple[4,5]元组,TS新增类型,固定长度数组
enumenumA, B枚举,TS中新增类型

2.2.1 number

number:任意

let a: number;
// a 的类型设置为了number,在以后的使用过程中a的值只能是数字
a = 10;
a = 33;
// a = 'hello'; // 此行代码会报错,因为变量a的类型是number,不能赋值字符串

2.2.2 string

string:任意字符串

let color: string = "blue";
color = 'red';

2.2.3 boolean

boolean:布尔值true或false

let isDone: boolean = false;

2.2.4 字面量

字面量:字面量不仅可以表示值,还可以表示类型,即所谓的字面量类型。也可以使用字面量去指定变量的类型,通过字面量可以确定变量的取值范围。

let a: 10; //a的值只能为10

//可以使用|来连接多个类型(|为联合类型表示取值可以为多种类型中的一种)
let b: 'male' | 'female'; //b的值只能二选一
b = 'male';
b = 'female';

let c: boolean | string;
c = true;
c = 'sd ';

2.2.5 any

any:任意类型

一个变量设置为any后相当于对该变量关闭了TS的类型检测,故不建议使用。声明变量如果不指定类型,则TS解析器会自动判断变量的类型为any(隐式的any)。

let d: any = 4;
d = 'hello';
let e ;
e=1;
e=true;
//d的值为any,它可以赋值给任意变量
let s:string
s=d;//这样变量s的类型检测也关闭了

2.2.6 unknown

unknown:类型安全的any,不能直接赋值给其他变量

let e: unknown;
e="hello"
let f:string
f=e;//报错 类型unkonwn不能赋值给string类型

2.2.7 void

void:void表示没有任何类型,和其他类型是平等关系,不能直接赋值:

声明一个void类型的变量没有什么大用,我们一般也只有在函数没有返回值时去声明。

//void用来表示空
function fn(): void 
    return undefined//除了undefined的其他类型的返回值会报错

2.2.8 never

never:不能是任何值

//never 表示永远不会返回结果 连undefined都不能返回,一般用来报错
function fn1(): never 
 throw new Error('报错了');


2.2.9 object

object:任意的JS对象

//1.定义对象结构的类型声明
/*
语法:属性名:属性值,属性名:属性值 
在属性名后边加上?,表示属性是可选的
*/

let b:  name: string; age?: number ;
b =  name: '孙悟空', age: 18 ;

//[xxx:string]:any 表示任意类型的属性
let c:  name: string; [propName: string]: any ;
c =  name: '猪八戒', age: 18, gender: '男' ;

//2.定义函数结构的类型声明
//我们一般会限制函数有几个参数,参数的类型,返回值的类型,可以以一种类似箭头函数的方式来声明一个函数类型的变量
/* 
语法:(形参:类型,形参:类型...) => 返回值
*/

let d: (a: number, b: number) => number;
d = function (n1, n2): number 
  return n1 + n2;
;

2.2.10 array

array:任意JS数组

/*
语法:类型[]或Array<类型> 
*/
//如string[]表示字符串数组 (在元素类型后面接上[])  Array<number>表示数字数组

let e: string[]
//or
let e: Array<string>;

2.2.11 tuple

tuple: 元组,TS新增类型,就是固定长度(数量)数组

元组中包含的元素,必须与声明的类型一致,数量要对应,且顺序也要一一对应

/* 
语法:[类型,类型,类型] 
*/

let h: [string,string,number];//里面两个字符串类型,一个数字
h = ['s', 'f',1];//必须对应两个字符串,一个数字,顺序也不能变化

2.2.12 enum

比如我们在定义一个对象的时候 let person = name: ‘zs’, gender: ‘male’ 。像gender这种属性的取值一般只有两个,所以在存储的时候用数字来代替,可以提高效率,可以定义0表示女性,1表示男性

enum:枚举,TS中新增类型,把所有可能的情况全部列出来,适合用于多个值进行选择的场景,

//enum:结果是多个值进行选择
enum Sex 
  Male,
  Female,

let i:  name: string; sex: Sex ;
i = 
  name: '张三',
  sex: Sex.Male,
;
console.log(i.sex === Sex.Male);//true

2.2.13 联合类型

联合类型:表示取值可以为多种类型中的一种,使用 | 分隔每个类型。

let h: string | number;
h = '张三';
h = 18;

2.2.14 交叉类型

交叉类型:是将多个类型合并为一个类,使用&,表示同时,求并集

let j:  name: string  &  age: number ;
j =  name: '张三', age: 18 ;

交叉类型主要作用是将多个接口类型合并成一个类型,从而实现等同接口继承的效果,也就是所谓的合并接口类型

2.2.15 类型别名type

类型别名(type):用来给一个类型起个新名字。 仅仅是给类型取了一个新的名字,并不是创建了一个新的类型,类型别名常用于联合类型

type Message = string | string[];
let greet = (message: Message) => 
  // ...
;

2.2.16 类型断言

类型断言:有些情况下,变量的类型对于我们来说是很明确,但TS编译器并不清楚,可以通过类型断言来告诉编译器变量的类型,断言有两种形式:

//类型断言,可以用来告诉编译器变量的实际类型
/* 
语法: (变量 as 类型) 或  < 类型 > 变量 
 */

let e: unknown;
e='ss' //e实际是字符串,但e的类型设置的是unkonwn
let f: string;
f=e//报错

f = e as string;//告诉ts编译器e就是字符串,这样就不会出现上述f=e报错的情况
// 或
f = <string>e;

3 编译选项

3.1 自动编译文件

编译文件时,使用 -w 指令后,TS编译器会自动监视文件的变化,并在文件发生变化时对文件进行重新编译。

tsc xxx.ts -w

3.2 自动编译整个项目

一个文件一个文件的编译太麻烦了,我们可以对整个项目进行编译

首先在项目根目录下创建一个ts的配置文件 tsconfig.json,然后就可以使用tsc指令,编译项目下的所有ts文件为js文件,当然也可以开启监视模式tsc -w监视所有的文件

3.3 tsconfig.json的配置选项

tsconfig.json配置总览


  "compilerOptions": 
    "target": "es5",   // 指定 ECMAScript 目标版本: 'ES5'
    "module": "commonjs",  // 指定使用模块: 'commonjs', 'amd', 'system', 'umd' or 'es2015'
    "moduleResolution": "node",     // 选择模块解析策略
    "experimentalDecorators": true,  // 启用实验性的ES装饰器
    "allowSyntheticDefaultImports": true,   // 允许从没有设置默认导出的模块中默认导入。
    "sourceMap": true,   // 把 ts 文件编译成 js 文件的时候,同时生成对应的 map 文件
    "strict": true,  // 启用所有严格类型检查选项
    "noImplicitAny": true,  // 在表达式和声明上有隐含的 any类型时报错
    "alwaysStrict": true,  // 以严格模式检查模块,并在每个文件里加入 'use strict'
    "declaration": true,   // 生成相应的.d.ts文件
    "removeComments": true,   // 删除编译后的所有的注释
    "noImplicitReturns": true,  // 不是函数的所有返回路径都有返回值时报错
    "importHelpers": true,  // 从 tslib 导入辅助工具函数
    "lib": ["es6", "dom"],  // 指定要包含在编译中的库文件
    "typeRoots": ["node_modules/@types"],
    "outDir": "./dist",
    "rootDir": "./src"
  ,
  "include": [  
    "./src/**/*.ts"
  ],
  "exclude": [
    "node_modules",
    "dist",
    "**/*.test.ts",
  ]

3.3.1 include

  • 指定需要编译的ts文件目录,是一个数组,其中 *表示任意文件 **表示任意目录
  • 默认值:["**/*"]
"include":["src/**/*", "test/**/*"] // 所有src目录和test目录下的文件都会被编译

3.3.2 exclude

  • 指定不需要被编译的文件目录
  • 默认值:["node_modules", "bower_components", "jspm_packages"]
"exclude": ["./src/hello/**/*"]  // src下hello目录下的文件都不会被编译

3.3.3 extends

  • 定义被继承的配置文件(和引入外部文件类似)

    "extends": "./configs/base" // 自动包含configs目录下base.json中的所有配置信息
    

3.3.4 files

  • 指定被编译文件的列表,只有需要编译的文件少时才会用到(和include类似)

  • 列表中的文件都会被TS编译器所编译

    "files": [
    "core.ts",
    "sys.ts",
    "types.ts",
    "scanner.ts",
    "parser.ts",
    "utilities.ts",
    "binder.ts",
    "checker.ts",
    "tsc.ts"
    ]
    

3.3.5 compilerOptions

重要的编译选项,在compilerOptions中包含多个子选项,用来完成对编译的配置

target:设置ts代码编译的目标版本

对于选项有哪些可选值,我们可以随便写一个值,编辑器会提示我们有哪些可选值

"compilerOptions": 
    //可选值: “ES3”(默认), “ES5”, “ES6”, “ES2015”, “ES2016”, “ES2017”, “ES2018”, “ES2019”, “ES2020”, “ES2021”, “ESNext”.
    "target": "ES6"//ts代码将会被编译为ES6版本的js代码

lib:指定代码运行时所包含的库(宿主环境),一般运行在浏览器环境下的,就不需要自己单独设置这个

"compilerOptions": 
//可选值:“ES5”, “ES6”, “ES2015”...很多
    "lib": ["ES6", "DOM"]

module:设置编译后代码使用的模块化系统

"compilerOptions": 
//可选值:“CommonJS”, “AMD”, “System”, “UMD”, “ES6”, “ES2015”, “ES2020”, “ESNext”, “None”, “es2022”, “node12”, “nodenext”
    "module": "CommonJS"

outDir:指定编译后文件的所在目录

"compilerOptions": 
    "outDir": "./dist"//编译过的js文件将会生成到dist目录。可以将源码与编译后的代码分开存放

outFile:将所有的文件编译为一个js文件

  • 默认会将所有的编写在全局作用域中的代码合并为一个js文件,如果 module 制定了 None、System 或 AMD 则会将模块一起合并到文件之中,这种合并由打包工具去做。
"compilerOptions": 
    "outFile": "./dist/app.js"

rootDir:指定代码的根目录,默认情况下编译后文件的目录结构会以最长的公共目录为根目录,通过rootDir可以手动指定根目录

"compilerOptions": 
"rootDir": "./src"

3.3.6 其他配置

//是否对js文件编译,默认值:false
"allowJs":false,
    
//是否对js文件进行语法检查,默认值:false
"checkJs":false

//是否删除注释,默认值:false
"removeComments":false

//不生成编译后的文件,默认值:false
"noEmit":false

//当有错误的时候不生成编译后的文件,默认值:false
"noEmitOnError":false

//是否生成sourceMap,默认值:false
"remove":false

3.3.7 严格检查

//是否启用所有的严格检查(总开关),设置true后相当于开启了所有的严格检查,后面的检查不需要在写了,默认值:false
"strict":false

//是否总是以严格模式对代码进行编译,默认值:false
"alwaysStrict":false

//是否允许隐式的 any 类型,默认值:false
"noImplicitAny":false

//是否允许隐式的 this,默认值:false
"noImplicitThis":false

//严格检查bind、call和apply的参数列表,默认值:false
"strictBindCallApply":false

//严格检查函数的类型,默认值:false
"strictFunctionTypes":false

//检查是否存在空值,默认值:false  可以用a?.b判断a是否是空值
"strictNullChecks":false

//严格检查属性是否初始化,默认值:false
"strictPropertyInitialization":false

3.3.8 额外检查

//是否检查switch语句包含正确的break
"noFallthroughCasesInSwitch":false

//是否检查函数没有隐式的返回值
"noImplicitReturns":false

//是否检查未使用的局部变量
"noUnusedLocals":false

//是否检查未使用的参数
"noUnusedParameters":false

//检查不可达代码;true:忽略不可达代码,false:不可达代码将引起错误
"allowUnreachableCode":false

4 使用Webpack打包TS代码

通常情况下,实际开发中我们都需要使用构建工具对代码进行打包;TS同样也可以结合构建工具一起使用,下边以webpack为例介绍一下如何结合构建工具使用TS;

4.1 初始化项目

通过执行命令 npm init -y 初始化一个项目并创建package.json文件

使用tsc --init 创建ts的配置文件tsconfig.json

创建src/index.ts文件,用来编写ts代码

4.2 安装依赖

安装以下依赖包

npm i -D webpack webpack-cli webpack-dev-server typescript ts-loader clean-webpack-plugin
  • webpack:构建工具webpack

  • webpack-cli:webpack的命令行工具

  • webpack-dev-server:webpack的开发服务器

  • typescript:ts编译器

  • ts-loader:ts加载器,用于在webpack中编译ts文件

  • html-webpack-plugin:webpack中html插件,用来自动创建html文件

  • clean-wepack-plugin:webpack中的清除插件,每次构建都会先清除目录

4.3 配置webpack

根目录下创建webpack的配置文件webpack.config.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const  CleanWebpackPlugin  = require("clean-webpack-plugin");

module.exports = 
  // 指定入口文件
  entry: "./src/index.ts",

  // 开发模式使用,方便查错误
  devtool: "inline-source-map",

  // 配置服务器
  devServer: 
    contentBase: "./dist",
  ,

  // 指定打包文件所在目录
  output: 
    path: path.resolve(__dirname, "dist"),
    //打包后的文件
    filename: "bundle.js",
    environment: 
      arrowFunction: false, // 关闭webpack的箭头函数,可选
    ,
  ,

  // 用来设置引用模块
  resolve: 
   extensions: [".ts", ".js"],//以ts js结尾的文件都可以作为模块使用
  ,

  // 配置webpack的loader(打包使用的模块)
  module: 
      //加载规则
    rules: [
      
          //规则生效的文件
        test: /.ts$/,//以ts结尾的文件
          //要使用的loader
        use: 
          loader: "ts-loader",
        ,
          //排除的文件
        exclude: /node_modules/,
      ,
    ],
  ,

  // 配置webpack的插件
  plugins: [
     // 构建前清除目录
    new CleanWebpackPlugin(),
      //自动创建html文件
    new HtmlWebpackPlugin(
      template: "./src/index.html",
    软件开发入门教程网之TypeScript 基础语法

typeScript入门基础

《TypeScript 中文入门教程》 1基础数据类型

TypeScript基础入门之装饰器(三)

TypeScript 与 JavaScript 的区别(TypeScript万字基础入门,了解TS,看这一篇就够了)

TypeScript进阶开发——ThreeJs基础实例,从入坑到入门