您现在的位置是:首页 >技术交流 >typescript网站首页技术交流

typescript

iceylia 2024-06-21 18:01:02
简介typescript

1 引入

1.1 介绍

javascript变量的特点是变量类型是可变的,这是一个很好的特性,但是如果你在之前写了一个处理两个数字的函数,之后你忘记了里面只能用数字,你传了字符串进去,但是js不会报错,这使得debug麻烦起来

所以typescript在js的基础上进行了扩展,限制了一些东西,ts使得书写更复杂,但是更规范起来,而且也有了更加完善的报错信息。

ts能够兼容所有的js语法,所以你可以完全用js的语法也没有问题

1.2 配置环境

需要先安装nodejs,然后用npm安装typescript

npm i -g typescript

然后你创建一个ts文件,写一个普通的console.log
在这里插入图片描述
在这里插入图片描述

然后像使用javac一样使用tsc 文件来编译它,注意找准路径
在这里插入图片描述
这个时候就编译成js文件了。
在这里插入图片描述
这个时候有一个特点,如果你ts文件即使有ts的语法错误,tsc依旧能够编译成功。后面能够修改成有错不能编译成功。

2 类型声明

数据类型
ts的数据类型有number string boolean 字面量 any unknown void never object array tuple enum

声明
比如声明一个number类型

let a:number

如果你变量类型用错了,就会报错。
在这里插入图片描述
字面量类型
字面量就是一个确切的值

let a:10

这个时候a就只能是10

这种写法比较少见

联合声明

可以用|来放宽限制

let a:"male"|"female";
let b:boolean|number;

any类型
any就是所有类型,在ts中要避免使用这种情况,所有的let就相当于隐式的any

unknown类型
unknown是一个安全类型的any

如果是any,下面的代码可以成功,最后的结果是a也变成了any类型的,a的类型被改变了,ts的类型判断就没有意义了。

let b:any = 51;
let a:string;
a = b;

所以对于我们还不知道类型是什么的变量,可以先用unknown来声明

下面的代码会提示你b的变量未知,不能复制给string类型的a

let b:unknown=51;
let a:string;
a=b;

所以这个时候有三种方式来断言b是string类型的。

a = b as string;
if(typeof b === string){
	a = b;
}
a = <string>b;

暂时觉得第二种更加安全.

void类型

与c的函数一样,就是没有返回类型

object类型

如果直接声明一个object类型的也没有意义,万物皆对象

可以这样设置

let a:{name: string}//
let a:{name:string, age?:number}//可选属性
let c:{name:string, [propName:string]: number}//声明后面的number类型属性

let f:(a:number, b:number)=>number;//f是一个函数对象,声明了形参类型和返回类型的

数组类型

let a:string[]
let b:number[]
let c:Array<number>;

元组

元组是固定长度的数组,性能比可变长度的数组要好

let h:[string, number];
h = ["hello", 123];

enum枚举

这是ts中新增的类型

enum Gender{Male, Female};//这里对应的值是多少不重要了,有点像是map
let i:{name: string, gender:Gender};
i = {name:"xxx", gender:Gender.Male}
console.log(i.gender === Gender.Male);

类型别名

type myType = 1|2|3|4
let k:myType;

函数声明
下面的函数就能声明参数类型和返回类型

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

隐式声明

a这个时候会直接被解析成bool类型

let a = false;

3 编译选项

3.1 编译多个文件

watch监视模式

每次ts修改想要得到编译后的js需要每次使用tsc命令

可以用tsc app.ts -w开启监视模式,每次修改的时候都会自动编译了。

但是当文件多的时候很麻烦。

tsconfig.json引入

所以我们需要一个类似c里面makefile的文件来设置编译规则,让它自动编译所有的文件,并且可以设置编译成哪个版本的js,es3还是es5还是es6

先在底下创建一个tsconfig.json的文件,就可以在里面设置编译规则。
在这里插入图片描述
就算这个时候你json文件里面什么都不写,只写一个json的大括号,然后使用tsc,也能自动编译同目录下所有的ts文件,以及同目录下子文件ts

include

tsconfig是默认编译根目录下所有的ts文件,include是指定要编译的文件。

指定编译src底下的所有ts文件

{
	"include": [
		"./src/**/*"
	]
}

其中**表示任意目录,*表示任意文件

exclude

指定不需要被编译的文件,一般不需要设置

有一个默认值

"exclude":["node_modules", "bower_components", "jspm_packages"]

extends
指定直接使用哪个文件里面的json

3.2 compilerOptions

编译选项是配置文件中非常重要的配置选项,与include同级

target

编译版本,默认是es3,兼容性较好

"compilerOptions":{
	"target": "ES5"
}

module

模块化规范,比如comonjs或者es6,假如不知道有哪些选项,就乱填一个让它报错也行。

"module": "es2015"//也就是es6

lib

指定使用到的库

document也用到了名为dom的库。

一般不用设置它,默认选项就足够了。

outDir

设置编译输入的位置。

"outdir": "./dist"

outFile

将编译后的js合并成一个文件。

"outFile": "./dist/app.js"

会将全局作用域中合并,用的也比较少。

allowjs

是否编译js文件,默认是false。

"allowJs":true

checkJs

是否检查js文件语法,默认也是false。

true之后就会用ts的语法来检查js文件。

removeComments
是否移除注释,默认是false

noEmit

不生成编译后文件。用的少。只能用来检查语法。

noEmitOnError

ts语法错误时不编译成js


下面就是语法的严格检查了。

alwaysStrict

编译后的文件默认不使用严格模式,严格模式的性能要好一点

模块化文件就是在严格模式之下了,所以如果用到了import 和export的时候不会有"use strict"

noImplicitAny

不允许使用隐式的any,默认false

比如let a = 5就是一个隐式的。

noImplicitThis

不允许使用隐式的this,默认false

strictNullChecks

严格检查空值,当你用dom查询一个元素的时候,可能这个元素不存在,但是你将它赋值给一个变量了,这个变量就有可能是空值。

let test1 = document.getElementById("test1");
test1.addEventListener("click", ()=>{});

可以设置

if(test1){
	test1.addEventListener("click",()=>{});
}

strict
所有严格检查的总开关

将strict设置为true就可以不设置上面的严格检查了。

建议打开。

4 webpack配置

这一步需要有webpack基础,假如是使用vue和react就不需要自己配置了。

除了安装webpack必须的webpack webpack-cli

安装打包ts的文件typescript和ts-loader

npm i webpack webpack-cli ts-loader typescript -D

module里面的配置

module: {
	rules: [
		{
			test: /.ts$/,
			use: "ts-loader",
			exclude: /node-modules/
		}
	]
}

5 类

类的用法和js中es6的类差不多。

class Person{
	//实例属性 
	name:string = "孙悟空";
	readonly id:string = 123;
	static sayHello():void{
		console.log("hello");
	}
}

构造函数

class Dog(){
	name:string;
	age:number;
	constructor(name: string, age:number){
		this.name = name;
		this.age = age;
	}
}
const dog = new Dog("131", 12);

接下来的继承 super 抽象类, 接口都和java差不多。

抽象类

抽象类只能用来继承,不能实现,也可以在里面写抽象方法。

abstract class Animal{
	name:string;
	abstract sayHello:void;
}
class Dog extends Animal{
	sayHello(){
		console.log("31113");
	}
}

接口

接口就是用来定义一个类的结构的。

type mytype = {
	name: string,
	age: number
};
const obj1:mytype = {
	name: "ss",
	age: 11,
}
interface mytype2 = {
	name: string;
	age: number;
}
//可以用来替代type来声明对象
const obj2:mytype2 = {
	name: "3131",
	age: 11,
}
//需要实现接口中的所有内容
class myClass implements mytype2{
	name: string,
	age: number
}

private与public

private不能被直接访问,只能在类内部使用,可以用getter和setter设置。

protected比起private还能在子类中使用。

public就没有限制了。

class Person{
	private _name:string;
	private _age:number;
	get name(){
		return this._name
	}
	set name(value){
		 this._name = value;
	}
}

泛型

//类型不确定的时候,用fn<T>来声明函数
functin fn<T>(a:T):T{
	return a;
}
fn(10);
fn<string>("hello");

但是这样写的话限制太少了。

可以用接口给泛型加限制。

interface Inter{
	length: number;
}
function fn<T extends Inter>(a:T):number{
	return a.length;
}

这个时候a必须实现inter接口,也就是T类型的变量必须有length这个属性。

6 导入外部资源的问题

js包
如果你开启严格模式用ts导入js的包,那么会提示你包不存在。

解决方法有两个

1 正式一点的包会有专门为ts服务的包,一般是@types/包名
2 定义一个declaration.d.ts,这样写,比如我想要在ts中导入gsap包,declare module "gsap";

注意在tsconfig.json中将declaration.d.ts也纳入编译中

{
    "compilerOptions": {
        "module": "ES2015",
        "target": "ES2015",
        "strict": true
    },
    "include": ["src", "declaration.d.ts"]
}

导入图片

也需要在declaration.d.ts中将各个类型的图片定义成module

declare module "gsap";
declare module "dat.gui";
declare module '*.svg'
declare module '*.png'
declare module '*.jpg'
declare module '*.jpeg'
declare module '*.gif'
declare module '*.bmp'
declare module '*.tiff'

然后就可以和模块一样导入这张图片,在需要使用图片的地方直接放入这个对象即可。

import imag2 from "../assets/textures/bg.jpg"
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。