首页 前端知识 TypeScript快速入门

TypeScript快速入门

2024-05-18 18:05:55 前端知识 前端哥 175 628 我要收藏

TypeScript快速入门

Vue3完全拥抱ts,学习与掌握ts已是燃眉之急!

1、TypeScript编译器的安装

nodetypescript版本对应关系如下

https://blog.csdn.net/zsh501736479/article/details/128489424

因为我电脑的node版本是v10.12.0所以使用npm安装typescript时要指定版本,如

npm install typescript@4.1.2 -g

验证安装是否成功,终端命令行输入tsc即可,如

laizhenghua@laizhenhuadeAir bin % tsc
Version 4.1.2
Syntax:   tsc [options] [file...]
...
# 输出一些说明信息就安装成功了

如何使用tsc呢?tsc (typescript compile)的作用就是将.ts文件编译成js文件,类似javac命令。以至于可以让node或者是浏览器直接执行,例如

dist.ts

export { }
let msg: string = 'hello typescript'
console.log(msg) // hello typescript

进行编译tsc ./dist.ts后会得到dist.js文件,这个文件就可以直接用node执行,如

laizhenghua@laizhenghuadeMacBook-Air code % tsc ./dist.ts 
laizhenghua@laizhenghuadeMacBook-Air code % node ./dist.js
hello typescript

2、TypeScript数据类型

1、常见的数据类型

类型举例描述
number1,123,-45任意数字
string‘hello’任意字符串
booleantrue,false布尔值
any*任意类型
unknown*类型安全的any
void空值(undefined)没有值或者是undefined
never没有值不能是任何值
object{}任意的js对象
array[]任意的js数组
tuple[2,3]ts新增的数据类型也就是固定长度的数组
enumenum {A, B}枚举,ts新增的数据类型

2、类型申明写法

// 1.先申明再赋值
let a: number = 1;
// 2.声明和赋值同时进行(ts中也有变量类型自动推断,推断出来后这个变量只能该类型的值)
let b = '123';
// b = 1 会报错

// 3.字面量或常量的申明
let a: 10;
a = 10; // 可以赋值
a = 11; // 报错

// 4.可以使用 | 来连接多个类型(联合类型)
let b: 10 | 11; 
b = 10; // 可以赋值
b = 11; // 可以赋值

// 5.函数返回值
function sum(a: number, b: number): number {
    return a + b;
}
// 6.对变量关闭类型检测(回归原始js)
let key: any; // 也可以写成 let key; 隐式声明any
key = 1;
key = true;
key = 'abc'

// 7.unknown类型也可以关闭类型检测
let key: unknown;
key = 1;
key = true;
key = 'abc'

// 8.unknown实际上就是一个类型安全的any 不能直接赋值给其他变量
let primary: string;
primary = key; // 报错 不能直接赋值给其他变量

// 9.类型断言
let primary: string;
primary = key as string; // 告诉解析器就是一个string
// primary = <string> key;

// 10.对象写法
let d1: {name: string};
// 强制要求对象的 key-value 结构保持一致
d1 = {name: 'alex'};
// d1 = {name: 'alex', age: 12} 报错
let d2: {name: string, age ? : number}; // ? 表示age属性是可选的有没有都可以
d2 = {name: 'alex'};

// 任意属性写法
let d3: {name: string, [propName: string]: any};

// 11.函数变量写法
let fn: (a: number, b: number) => number;

fn = function(a: number, b: number): number {
    return a + b;
}

// 12.数组变量写法(ts中要求数组中元素类型必须保持一致)
let list: string[];
list = ['1', '2'];
let dic: Array<string>;
dic = list;

// 13.元组(固定长度的数组)
let a: [string, string];
a = ['1', '2'];

3、为什么要加数据类型?消除一些安全隐患,让程序变得可控制

// js
function sum1(a, b) {
    return a + b;
}
sum1(1, "123") // 不报错,存在一些不确定的安全隐患

// ts
function sum2(a: number, b: number) {
    return a + b;
}
sum2(1, "123") // 报错信息:Argument of type 'string' is not assignable to parameter of type 'number'.

3、TypeScript编译选项

1、自动编译ts文件

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

tsc dist.ts -w

2、自动编译当前目录下的所有ts文件

配合tsconfig.json配置文件,可以编译当前配置文件所在目录下的所有ts文件,例如

tsconfig.json

{
    // 无需申明任何配置项,执行tsc 也能变异当前配置文件所在目录下的所有ts文件
}

在这里插入图片描述
3、tsconfig.json的配置选项

tsconfig.json是一个JSON文件,可以编写注释。添加此配置文件后,只需要tsc命令即可完成对整个项目的编译,那个它有哪些配置选项,去控制编译行为?

/*
include 
    1.定义希望被编译的文件所在的目录
    2.默认值 ["**/*"]
    3.应用场景 项目中可能会有很多ts文件,我们不需要每个ts文件都编译,就可以使用include控制编译的目录或文件
exclude
	1.排除不想编译的目录或者是文件
	2.默认值 ["node_modules", "bower_components", "jspm_packages"]
extends
	1.指定被继承的配置文件
	2.了解即可,很少用到
files
	1.指定被编译的文件,只有需要编译的文件很少时才需要用到
*/

{
    // 只编译 src 目录下的任意ts文件
    "include": [
        "./src/**/*"
    ],
    "exclude": [
        "./src/test.ts"
    ]
}

// 以上配置项都比较简单 compilerOptions 编译选项是配置文件中非常重要也是比较复杂的配置选项
/*
compilerOptions 配置选项是一个对象
    1.target 用来指定ts被编译为的ES的版本 默认是ES3
    2.module 指定要使用的模块化的规范 可选值有 "CommonJS", "AMD", "System", "UMD", "ES6", "ES2015", "ES2020", "ESNext", "None", "ES2022", "Node16", "NodeNext"
    3.lib 用来指定项目中要使用的库(一般不用管这个配置项)
    4.outDir 用来指定编译后文件所在的目录
    5.outFile 将全局作用域中的代码(编译后的代码)合并到一个文件中
    6.allowJs 是否对js文件进行编译 默认是 false
    7.checkJs 是否检查js代码是否符合语法规范 默认是 false
    8.removeComments 编译时候是否移除ts代码中的注释
    9.noEmit 不生成编译后的文件(检查ts语法)
    10.noEmitOnError 编译时当有错误时不生成编译后的文件
    11.alwaysStrict 用来设置编译后的文件是否使用严格模式
    12.noImplicitAny 是否不允许出现隐式的 any 类型
    13.noImplicitThis 是否不允许出现隐式的 this 指向(不明确的this)
    14.strictNullChecks 是否开启严格检查空值
    15.strict 所有严格检查的总开关(就不用一个个声明为true)
*/
{
    "include": [
        "./src/**/*"
    ],
    "compilerOptions": {
        "target": "ES2015",
        // "module": "ES2015",
        "outDir": "./dist",
        "outFile": "./dist/app.js",
        "allowJs": false,
        "checkJs": false,
        "removeComments": false,
        "noEmit": false,
        "noEmitOnError": false,
        "alwaysStrict": true,
        "noImplicitAny": true,
        "noImplicitThis": true,
        "strictNullChecks": true,
        "strict": true
    }
}

4、TypeScript使用weback打包

实际开发中我们很少自己编写tsconfig.json然后直接使用ts编译器编译代码。一般都是借助打包工具,比如说webpackwebpack有完整的入口、出口、插件等功能,对代码分割、模块化、去掉死亡代码、提取公共代码也更加完善。

1、初始化测试项目,得到package.json文件,在此文件中引入webpack相关依赖。

# 初始化
laizhenghua@laizhenghuadeMacBook-Air ts % npm init -y
# 安装相关依赖(因为node版本是v10.12.0,需要指定版本号)
laizhenghua@laizhenghuadeMacBook-Air ts % npm install - D webpack@5.6.0 webpack-cli@4.2.0 typescript@4.1.2 ts-loader@8.0.11 @types/node@14.0.4

2、编写webpack配置文件webpack.config.js

webpack.config.js

const path = require('path');

// webpack所有配置信息都写在 module.exports = {}
module.exports = {
    // 指定入口文件
    entry: './src/index.ts',
    // 指定打包文件所在的目录(出口)
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'dist.js'
    },
    // 指定webpack打包是要使用的模块
    module: {
        // 指定要加载的规则
        rules: [
            {
                // test指定的是规则生效的文件
                test: /\.ts$/,
                use: 'ts-loader',
                // 排除的模块
                exclude: /node_modules/
            }
        ]
    }
}

3、编写tsconfig.json配置文件

tsconfig.json

{
    "compilerOptions": {
        "outDir": "./",
        "module": "ES2015",
        "target": "ES2015",
        "strict": true
    },
    "exclude": [
        "node_modules",
        "dist"
    ]
}

4、最后我们只需添加编译命令即可

package.json

{
  "name": "ts",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    // 注意添加的是这一行
    "build": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "ts-loader": "^8.0.11",
    "typescript": "^4.1.2",
    "webpack": "^5.6.0",
    "webpack-cli": "^4.2.0",
    "@types/node": "^14.0.4"
  }
}

5、测试(检查输出的文件)

在这里插入图片描述


以上就是整个ts项目编译、打包过程。然而要想编译得到的js文件可以在浏览器中执行,我们还需将html文件也一起打包~

以下为webpack扩展部分:

1、安装html-webpack-plugin,用于自动生成html文件

laizhenghua@laizhenghuadeMacBook-Air ts % npm install html-webpack-plugin@4.5.0 --save-dev

2、配置插件

webpack.config.js

const path = require('path');
// 引入html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin');

// webpack所有配置信息都写在 module.exports = {}
module.exports = {
    // 指定入口文件
    entry: './src/index.ts',
    // 指定打包文件所在的目录(出口)
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'dist.js'
    },
    // 指定webpack打包是要使用的模块
    module: {
        // 指定要加载的规则
        rules: [
            {
                // test指定的是规则生效的文件
                test: /\.ts$/,
                use: 'ts-loader',
                // 排除的模块
                exclude: /node_modules/
            }
        ]
    },
    // 配置webpack插件
    plugins: [
        new HtmlWebpackPlugin({
            title: "TypeScript Test",
            // template: "./src/index.html" 使用模版构建
        })
    ],
    // 用来设置引用模块
    resolve: {
        // ts和js都可以做为模块在其他模块中引入
        extensions: ['.ts', '.js']
    }
}

5、TypeScript面向对象

面向对象是程序中一个非常重要的思想,很多初学者理解起来也非常困难,这是一个比较深奥的问题,其实不然简单理解就是对象就是程序中的一切,程序中所有的操作都需要通过对象来完成。

js中常见对象有:

  1. 可以使用window对象操作浏览器,例如window.open('https://www.baidu.com')
  2. 可以使用document对象操作网页,例如document.createElement('a')
  3. 可以使用console对象操作控制台,例如console.log('hello world')

然而面向对象,三言两语根本解释不了,需要自己在漫长的学习与使用中慢慢领悟。

5.1、class(类)

前面我们提到,面向对象中对象就是程序的一切!要想创建或实例化对象,必须先有类,类就是对象的模型或者是模版(相当于告诉CPU在内存中要创建怎样的数据结构),基于这个模版才能实例化出对象。

ts中定义一个类也很简单,如下:

export { }
// 定义一个Person类
class Person {
    // 普通属性 属性名: 数据类型
    name: string;
    age: number;
    gender: number;

    // 静态属性(不用实例化对象也能访问可以通过 Person.handNum 访问)
    static handNum: number = 2;
    // 只读属性(不能被修改类似Java中的final关键字)
    readonly eyes: number = 2;
    // 静态只读属性
    static readonly foots: number = 2;

    // 声明构造方法
    constructor(name: string, age: number, gender: number) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    // 定义方法
    eat() {
        console.log('人会吃');
    }
    // 静态方法
    static run() {
        console.log('人会跑')
    }
}

const person = new Person('alex', 22, 0);
console.log(person);

console.log(Person.foots);

Person.run();
5.2、extends(继承)

一个新类从已有的类获得其已有的特性(获取其特性的同时还可以对新类进行扩展),称之为类的继承。继承也有很多好处!减少代码的冗余,提高代码的复用性,便于功能的扩展。

注意子类继承父类后,子类拥有了父类的所有结构。

export { };

class Person {
    name: string;
    age: number;

    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }

    eat(): void {
        console.log('吃饭');
    }
}

// ts中继承的关键字也是 extends
class ChinesPerson extends Person {
    // 方法的重写
    eat(): void {
        console.log('用筷子吃饭')
    }
    // 对 Person类 进行扩展
    run(): void {
        console.log('人会走路');
    }
}

const person = new Person('alex', 22);
person.eat(); // 吃饭

const chinesPerson = new ChinesPerson('马超', 22);
chinesPerson.eat(); // 用筷子吃饭
chinesPerson.run(); // 人会走路

ts中是单继承还是多继承?

在这里插入图片描述

ts中如何使用super关键字?

同其他语言一样tssuper也是代表父类,可以在子类中调用父类的方法。

export { };

class Person {
	// 属性可以任意修改将会导致对象中的数据变得非常不安全,因此将属性私有化是最好的
    private name: string;
    private age: number;
    public static eyes: number = 2;

    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }

    eat(): void {
        console.log('吃饭');
    }
    public getName(): string {
        return this.name;
    }
    public setName(name: string): void {
        this.name = name;
    }
    public getAge(): number {
        return this.age;
    }
    public setAge(age: number): void {
        this.age = age;
    }
}

class ChinesPerson extends Person {
    // 如果在子类中申明构造方法 必须先手动调用父类的构造方法
    constructor(name: string, age: number) {
        super(name, age);
        this.setName(name);
    }
    // 方法的重写
    eat(): void {
        super.eat();
        // 虽然是调用父类的获取属性方法,但是属性还是子类的
        console.log('super name = ' + super.getName()); // super name = 马超
        console.log('用筷子吃饭');
    }
    // 对 Person类 进行扩展
    run(): void {
        console.log('人会走路');
    }
}

const person = new Person('alex', 22);
person.eat(); // 吃饭
console.log(person.getName());

const chinesPerson = new ChinesPerson('马超', 22);
chinesPerson.eat(); // 用筷子吃饭
chinesPerson.run(); // 人会走路
5.3、abstract class(抽象类)
const person = new Person('alex', 22);

对于Person类来说泛指各种各样的人范围太大了,所以Person类做为超类我们不希望以超类来创建对象,而是做为父类抽象一些属性与方法供其他类去继承与扩展,因此抽象类出现了。

abstract关键字修饰的类称为抽象类,抽象类不能被实例化,是用来被继承的,在抽象类中被abstract修饰的方法叫抽象方法,抽象方法没有方法体,抽象类的子类需要重写父类的抽象方法。

export { };

abstract class Person {
    // 抽象方法
    public abstract eat(): void;
}

class Chines extends Person {
    public eat(): void {
        console.log('用筷子吃饭!');
    }
}
5.4、interface(接口)

比抽象更抽象的结构就是接口!

接口就是规范、标准、契约,事先制定好一组规则,大家都要遵守!例如数据库驱动DriverDriver是一个接口事先定义好了connect()、acceptsURL()等没有方法体的方法,具体怎么连接数据库需要不同的厂商自己去实现(MySQL、Oracle等需要实现Driver接口,重写connect()方法实现数据库的连接逻辑)。

然而在ts中,接口可以定义一个类的结构(一个类中应该包含哪些属性与方法)

// p1只可以定义一次
type p1 = {
    name: string;
    age: number;
}
const p1_impl: p1 = {
    name: 'alex',
    age: 22
}

// p2可以定义多次前提是要使用interface修饰
// 接口只能定义对象的结构不考虑实际值
interface p2 {
    name: string;
    age: number;
}

// 将接口当成类型去使用
const p2_impl: p2 = {
    name: 'alex',
    age: 22
}

ts中接口就是限制类的结构,定义的方法都只能是抽象方法

export { };

interface Person1 {
    name: string;
    eat(): void;
}

interface Person2 {
    age: number;
    run(): void;
}

// 单继承多实现
class Chines implements Person1, Person2 {
    name: string;
    age: number;

    eat(): void {
        console.log('开始干饭')
    }

    run(): void {
        console.log('开发跑步')
    }
}

6、TypeScript泛型

所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。

这个类型参数将在使用时(例如继承或实现这个接口,用这个类型声明变量、创建对象时)确定(即传入实 际的类型参数,也称为类型实参)。

// 泛型函数
function fn<T>(param: T): T {
    return param;
}

console.log(fn(10));
console.log(fn('abc'));
// 指定泛型
console.log(fn<boolean>(true));

END

转载请注明出处或者链接地址:https://www.qianduange.cn//article/8749.html
标签
评论
发布的文章
大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!