前言
TypeScript is JavaScript with syntax for types.
这是是官网对TypeScript的定义。作为JavaScript的超集,TypeScript重点提出了类型系统。如今 TS 已经受到了广泛的应用,它坚持与 JavaScript 核心语法标准 ECMAScript 同步发展,对于熟悉JavaScript的开发人员来说也是十分容易上手的。关于 TypeScript 的优缺点就不过多阐述了,下面进入正题
安装
TypeScript 的命令行工具全局安装方法:
npm install typescript -g
安装完成后,我们可以在任何地方通过执行命令tsc [tsfile]
编译 typescript 文件
数据类型
TypeScript支持与JavaScript几乎相同的数据类型。类型声明语法如下:
let [variable]: [type]
JavaScript 中的数据类型包括:原始数据类型和引用类型。原始数据类型包括:boolean、number、string、null 和 undefined,以及ES6新增的Symbol和BitInt。
原始基本类型
下面是五种基本类型对应的声明写法:
类型 | 示例/值 |
---|---|
boolean | let b: boolean = true false |
number | let num: number = 123 |
string | let str: string = "Hello World" |
null | let x: null = null |
undefined | let x: underfined = underfined |
undefined 和 null 是所有类型的子类型。这两个类型的值可以赋值给其他类型的变量:
// 这样不会报错
let num: number = undefined
// 这样也不会报错
let num: number = null
除了基本类型,TS 还提供了void、any、字面量、等类型:
void:表示没有值,通常用于描述方法的返回值
any:表示任意类型,官方并不推荐使用,这样就丢失了类型的特性
字面量:声明的类型就是变量的值,字面量可以是一个可以是多个
let a: 3 // 变量的值只能是3
a = 4 // 这样赋值会报错
let a: 3 | '3' // 变量的值只能是3或'3'
a = '3' // 这样赋值是正确的
数组与元组(tuple)
定义一个数组,通常有两种方式:type[]
、数组泛型。
let arr: number[]
let arr: Array<number>
通过类型声明限制了数组存储的数据类型,例如上面声明的两个数组里就只允许存放 number 类型的数据。
元组(tuple)是 TypeScript 新增的概念,它与数组类似但允许列表内出现不同的类型数据,且必须在声明时固定长度。它的定义方式如下:
let tup: [string, number] = ['小明', 25]
函数类型
在 JavaScript 中,定义函数通常有两种方式:函数声明 和 函数表达式。对于一个函数,TypeScript 需要对入参类型、返回类型进行约束:
// 函数声明
function sum(x: number, y: number): number {
return x + y
}
// 函数表达式
let sum = function (x: number, y: number): number {
return x + y
};
上面分别用函数声明和函数表达式两种方式定义了一个带有两个number类型的入参及number类型返回值的函数。如果一个函数没有返回值,可声明为void。在这样的声明约束下,入参和返回必须严格遵循约束,不可少传、多传。
可选参数
如果对函数的入参有不确定性,可以用?
设置可选参数:
function buildName(firstName: string, lastName?: string) {
if (lastName) {
return firstName + ' ' + lastName
} else {
return firstName
}
}
需要注意的是,可选参数必须接在必需参数后面。另外,在 ES6 提出的参数默认值在 TS 中会被识别为可选参数,同样必须接在必需参数后面。
联合类型
当我们声明的变量有可能是多种类型时,可以声明为联合类型:string | number
。当一个变量被声明为联合类型时,在使用这个变量时,只能调用联合类型所共有的属性及方法
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
面向对象
在早期的 JavaScript 中,是通过构造函数实现类的并通过原型链实现继承。在 ES6 才引入了类和 class 语法,TypeScript 除了完全支持 class 语法,同时增加了一些新的东西。
修饰符
TypeScript 引入三种属性修饰符:public、private、protected
- public:修饰的属性或方法是公有的,可以在任何地方访问,也是默认的修饰符
- private:修饰的属性或方法是私有的,不允许在声明它的类的外部访问。若需要访问私有属性,可以配置寄存器(getter/setter)属性访问或修改。
- protected:修饰的属性或方法是受保护的,与 private 修饰符的行为很相似,但不同的是 protected 修饰的成员在子类中允许访问
另外要提一个修饰符,叫:readonly,只读属性修饰符。被修饰的属性只允许读取不允许修改,要注意的是,如果它和其他访问修饰符同时存在的话,需要写在其后面。
抽象类
抽象类既是当我们写一个类时,只是希望它作为父类继承而不希望直接使用该类的实例。对于这样的类,TypeScript 引入了 abstract 关键字对其进行修饰,同时类中的方法也必须用这个关键字修饰。
abstract class Animal {
public name
public constructor(name) {
this.name = name
}
public abstract giao()
}
let animal = new Animal()// 这样会报错
需要注意的是,在抽象类中定义的抽象方法必须在子类进行实现。
class Cat extends Animal {
public giao() {
console.log('喵!');
}
}
接口
我们知道类之间可以通过继承实现功能拓展,但是一个类有且只能继承一个类。TypeScript 引入了接口的语法,接口是面向对象中的一个重要概念,有时候不同类之间可以有一些共有的特性,这时候就可以把特性提取成接口,用implements
关键字来实现。相比于类的单继承,接口是允许类实现多个。
interface Eat {
eat(): void
}
interface Say {
say(): void
}
class Person implements Eat, Say {
private name
eat(): void {}
say(): void {}
}
泛型
泛型是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
一个例子
我们编写一个方法,希望把输入的值返回出来。
function fun(a: number): number {
return a
}
在这里,我们写死了参数类型为 number,但是如果希望 string 或别的类型也用到这个方法就不可行了。于是引出泛型的写法:
function fun<T>(a: T): T {
return a;
}
在上例中,我们在函数名后添加了<T>
,其中 T 用来指代一种数据类型,同时也为函数返回值指定为 T 类型。在调用时,通过传入参数的具体类型推断 T 的类型。
多个类型参数
定义泛型的时候,可以一次定义多个类型参数:
function fun<T, K>(a: T, b: K): T {
return a;
}
泛型约束
在使用泛型变量时,因为不知道它是哪种类型,所以不能随意的操作它的属性或方法。我可以通过对泛型进行约束,保证变量类型属于我们所确定的范围:
interface Lengthwise {
length: number;
}
function outLength<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
上诉例子,我们通过extends
限制变量类型必须实现了 Lengthwise 接口,保证变量有length属性。
泛型接口
interface List<T> {
[index: number]: T,
length: number
}
let list:List<string> = ['a', 'b', 'c']
泛型类
class GenericNumber<T> {
value: T;
add: (x: T, y: T) => T;
constructor(value: T) {
this.value = value
}
}
let number = new GenericNumber<number>(1)
number.add = function (x, y) {
return x + y
}
类型别名
通过type
关键字,我们可以自己定义类型。比如有一组属性都是相同的联合类型,定义类型别名就很有必要。
type myType = number | string
interface Obj {
attr1: myType
attr2: myType
}
let obj: Obj = {
attr1: 1,
attr2: '2'
}
类型断言
我们可以手动对一些不确定的值指定一个类型,场景多用于联合类型和类型别名。
as
语法
type myType = number | string
function getLength(params: myType): number {
const str = params as string
if (str.length) return str.length
return str.toString().length
}
<类型>
语法
type myType = number | string
function getLength(params: myType): number {
const str = params<string>
if (str.length) return str.length
return str.toString().length
}
结语
本篇博客写于近期复习 TypeScript 的简单总结,这些对于入门阶段的知识是完全够了。更多内容还是参考官方文档。
参考资料:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。