文章目录
- TypeScript 基础
- 基础类型
- 循环
- 函数
- 数组
- 元组
- 联合类型
- 接口
- 类
- 断言
TypeScript 基础
这里是我首次接触 TypeScript
的学习笔记。
基础类型
这里需要注意的是 null
和 undefined
是所有基础类型的子集,这意味着,你可以像这样赋值:
let varA:number = 1234;
varA = undefined;
但是不能反过来,将 1234
赋值给本是 undefined
的 varA
在 typescript
中新出现的一种基础数据类型,never
,是其他类型(包括 null
和 undefined
的子集,代表从不会出现的值。
这就意味着,你不能够再利用 never
去给 null
和 undefined
以及其他基础类型赋值,never
只能被 never
赋值。在函数中它通常表现为抛出异常或无法执行到终止点(例如无限循环)
只用 any 类型可以使用.运算符对其中的变量进行赋值。
循环
for… in 循环需要注意:
const list:string = '1234556';
for (const item in list) {
}
这里的 item
不能预先定义其类型。
函数
在 typescript
中,如果函数拥有返回值(或者没有,类型为 void
)需要为函数的返回值进行变量类型声明,函数的参数也必须带变量类型的声明:
function add(x:number, y:number):number {
return x + y;
}
function caller(x:number, y:number):void {
console.log(add(2, 3));
}
和 js
中不同,如果我们规定了参数,那么这些参数必须传入,当然,可以利用 ?
将某些参数定位可选参数
function scream(a:string, b?:string) {
if (b) {
console.log(a, b);
} else {
console.log(a);
}
}
在普通的 ES6
中:
let scream = (x: string, y:string): string => `he sayed ${x} and ${y}!`
只是对右侧的匿名函数做了类型定义,而左侧的变量是通过赋值类型推论而推断出来的。如果我们需要手动给 scream 添加类型,则应该是这样的:
let scream: (x: string, y: string) => number = function (x: string, y: string): string {
return `he sayed: ${x} and ${y}!`;
}
不要混淆了 Typescript 中的 =>
和 ES6
中的箭头函数。
在 Typescript 类型定义中, =>
是用来表示函数的定义,左边是输入类型,需要用括号括起来,右边是输出类型。
重载函数,需要设置为每个重载方法设置独一无二的参数类型列表,参数数量不同你可以将不同的参数设置为可选。
function a(x:string):void {}
function a(x:number):void {}
function a(x:number, y?:string):void {}
数组
定义数组与之前定义变量不同,需要在变量类型后面加上 []
,或者利用数组的泛型,比如:
const arr_name: number[] = new Array<number>(4);
返回数组的函数,也要使用上面的方式:
function getSites() :string[] {
return new Array<string>('Google', 'Baidu', 'Tencent', 'Facebook');
}
元组
一般来讲,数组的类型都是相同的(any 类型可以不同),如果存储的数据类型不同,则使用元组。
元组用来代表有限个数的数据类型任意的集合。
如:
const tom: [string, number] = ['tom', 25]
联合类型
联合类型(Union Type)可以通过管道(|
)将变量设置为多种类型,赋值时可以根据设置的类型来赋值。
const val:string|number;
val = 12;
console.log(val);
联合类型也可作为函数参数:
function disp(name:string|string[]) {
if(typeof name == "string") {
console.log(name)
} else {
var i;
for(i = 0;i<name.length;i++) {
console.log(name[i])
}
}
}
disp("Runoob")
console.log("输出数组....")
disp(["Runoob","Google","Taobao","Facebook"])
也可以作为函数的返回类型:
function testFunction(flag: boolean): string|number {
if (flag) {
return '12345';
} else {
return 1234567;
}
}
console.log(testFunction(false));
数组也可以使用。
接口
在 typescript
中 interface
不能被编译成 javascript
语法,这是 typescript
独有的。
接口在 typescript
中用来对对象或者函数进行一定的限制。
比如:
interface IPerson {
firstName: string,
lastName: string,
sayHi():string,
}
const Customer: IPerson = {
firstName: 'Tom',
lastName: 'Hanks',
sayHi: function():string {return 'Hi there'},
}
console.log(Customer.sayHi());
这就意味着,在实现该接口的对象中,必须要 firstName
、lastName
、sayHi
这三个属性。
接口中也可以使用 ?
来规定可选属性:
interface IPerson {
firstName: string,
lastName: string,
sayHi?():string,
}
const Customer: IPerson = {
firstName: 'Tom',
lastName: 'Hanks',
}
console.log(Customer.firstName);
接口可以继承,通过 extends
来进行继承,继承方式类似于 java。
类
基础的类的用法类似于 javascript
中的类的用法,只不过需要明确其中的变量类型
class Car {
// 字段
engine: string;
// 构造函数
constructor(engine: string) {
this.engine = engine;
}
// 方法
disp(): void {
console.log('发动机为:', this.engine);
}
}
typescript
中的类也只允许单继承,不允许多继承,但是允许多重继承。
断言
注意,不能滥用断言,断言可能会出现某些问题。断言会欺骗 typescript 编辑器,但是无法避免运行时错误。
断言也是有限制的,并不是一个类型都可以被被断言为任何另一个类型的。
具体来说,必须要 A 兼容 B,或者 B 兼容 A,那么两者可以互相断言。这是由于,Typescript 是一门结构类型系统,类型之间的对比指挥比较它们最终的结构,而会忽略它们定义时的关系。
所以:
- 联合类型可以被断言为其中一个类型
- 父类可以被断言为子类
- 任何类型都可以被断言为 any
- any 可以被断言为任何类型
- 要使得 A 能够被断言为 B,只需要 A 兼容 B 或 B 兼容 A 即可。
前四种情况都是最后一个的特例。