2022年了,作为一个前端开发,如果没听说过TypeScript的话,估计要被吐槽落伍了。因为工作需要,虽然自己更习惯使用JavaScript,但是还是不得不硬着头皮捡起TypeScript好好看看。本系列为TypeScript的学习笔记,后续也会有实战项目。
使用过js的都知道,js是非常灵活的,一个变量只要自己想要,可以是任何类型。这是因为JavaScript是解释型语言,没有编译阶段, 只有在运行时才能明确知道会是什么类型;TypeScript是静态类型的,重点在于确定类型, 这个在编译阶段就会有提示。ts是js的超集,是完全兼容js的,尽管如此,还是不建议ts和js混用,要么就全用ts,要么就全用js。
说明:本文以及后续的文章需要一定的JavaScript基础
环境准备
既然是学习ts,那么就需要准备ts的相关环境。
安装依赖
首先我们需要全局安装一个typescript
的依赖:
npm i -g typescript
安装typescript
后,使用时是tsc
命名。这个依赖可用于初始化ts项目,以及将ts文件编译为js文件,这样就可以在html文件中引入js文件,引入ts文件是不可以的。
typescript
虽然可以编译,但是不能直接运行js文件。如果我们要运行js文件,一般都需要依赖node环境,刚好有这么一个依赖:
npm i -g ts-node
ts-node
可以在node环境下直接运行ts文件,这样就方便学习了。
如下图所示,就表示环境准备好了:
代码编辑器建议使用VSCode,有使用记事本的大佬也是可以的。
创建项目
既然是学习项目,就简单点创建一个项目:
mkdir learning-of-typescript
cd learning-of-typescript
tsc init // 初始化ts项目,会创建一个tsconfig.json配置文件
git init // 可选,初始化git仓库,每天学了点什么,还是用版本记录一下,免得自己都搞忘了
项目已经创建好了,good good study。
基础
基本数据类型
布尔值
使用字面量创建,类型指定为boolean
let isBool: boolean = false;
boolean是基本数据类型,Boolean是构造函数,实例化出的对象是Boolean类型
let createBoolean: Boolean = new Boolean(1);
但是可以使用Boolean直接来创建一个boolean类型
let isBoolean: boolean = Boolean(false)
数字
number为数据类型,Number是其包装类型
let isNumber: number = 10;
isNumber = 0b1010; // 二进制,结果为10
isNumber = 0o744; // 八进制,结果为484
isNumber = Infinity; // 无穷值,有正负
isNumber = NaN; // 非数字,isNaN()
字符串
string为数据类型,String是其包装类型
let isStr: string = 'hello';
isStr = `hi ${isStr}`; // 模板字符串
其他数据类型
空值
JavaScript中没有空值的概念,但是typescript中可使用void表示没有任何返回值的函数
function voidFuc(): void{}
也可以用于声明变量,但是声明的空值变量,只能赋值为undefined或者null,前提是strictNullChecks为指定或者设置为false
let isVoid: void = undefined;
let isVoid: void = ''; // 编译错误
null和undefined是所有类型的子类型,被定义为null或undefined的变量,可以赋值给其他类型
let isNull:null = null;
// let num: number = undefined; // 前提是strictNullChecks为指定或者设置为false
// let num:number = void; // void不能赋值给除undefined和null外的类型
any
任意值类型。一般来说,定义变量并指定类型后,在后续的使用过程中不能赋值为其他类型的值。
let str:string;
str = 10; // 编译错误
如果定义为any任意值类型,那么在使用时也可以更改类型。任意值就表示可以是任意类型,不建议大量使用any,这将失去ts的特性
let isAny:any = 10;
isAny = 'hello';
既然任意值是可以为任意类型,那么也就可以调用任意方法,当然这些方法是有意义的。
如果在申明变量时,未指明类型,则默认未any类型。
let anyThing; // 类型为any
类型
类型推论
在定义变量时,虽然未指定类型,但是ts可通过初始值的类型推论出变量的类型。
let num2 = 10;
// num2 = 'hello'; // num2推论出类型为number,赋值为string类型时会编译出错
如果定义变量时,未指定类型,也没有初始值,那么其类型将会被推论为any
联合类型
表示值的类型可以是多种类型中的一种,联合类型采用|分割不同的类型。
let strAndNum: string | number;
strAndNum = 1;
strAndNum = 'hello';
// strAndNum = undefined; // 前提是strictNullChecks为指定或者设置为false
// strAndNum = false; // strAndNum可为string、number类型中的一种,但是不能为其他的
只能访问联合类型的所有类型中共有的属性和方法,因为不确定具体的类型。
strAndNum.split(','); // 可能会报错,如果根据类型推论能得到strAndNum的类型为string则编译正常,否则会报错
接口类型
除了基本的数据类型,有时候我们会使用一些自定义的数据类型,这种时候就需要使用接口。接口是对行为的抽象,使用方式比较灵活。需要注意,在使用接口定义变量时,变量赋值时必须和接口保持一致,不能多一些属性,也不能少一些属性。
interface Person1 {
name: string,
age: number
}
let student: Person1 = {
name: '张三',
age: 18,
// addr: '111', // 编译错误
}
可选属性
interface Person2 {
name: string,
age?: number
}
let student2: Person2 = {
name: '张三',
}
可选属性的意思是可以不存在该属性,但是如果出现了未在接口中定义的属性,那也是不行的。例如:
let student3: Person2 = {
name: '张三',
// sex: 'man', // 未在接口中定义的属性
}
任意属性
为了扩展,我们允许接口中存在任意属性
interface Person3 {
name: string,
age?: number,
[propName: string]: any
}
let student4: Person3 = {
name: '张三',
sex: 'man'
}
需要注意的是,一旦定义了任意属性,那么确定属性和可选属性都必须是任意属性的子类型。因为相对任意属性来说,确定属性和可选属性都只是它的特例。
只读属性
如果希望对象只能在创建时赋初始值,并且后续不可再更改,那么可以考虑使用只读属性。
interface Person4 {
name: string,
age?: number,
[propName: string]: any,
readonly id: number
}
let student5: Person4 = {
name: '张三',
sex: 'man',
id: 9527
}
// student5.id = 1234; // 无法修改只读属性,前提是已经初始化赋值了
总结
今天就先学这些,还得继续去搬砖,明天继续。
- 本文作为开篇,介绍了ts环境准备、项目创建以及一些基础知识
- 本文需要一定的js基础,有些知识可能没有讲完整
- 学习项目可参考:learning-of-typescript