TS-入门学习笔记
TypeScript 是 JavaScript 的一个超集,主要提供了类型系统和对 ES6 的支持。
与js相比,最大的有点是类型系统的引入,由于js本身是弱类型语言,所以天然不存在类型系统,这一方面使得js使用起来更简单,但同时也带来了一定的问题,所以ts重新引入了类型系统,带了了以下的优点:
类型系统实际上是最好的文档,大部分的函数看看类型的定义就可以知道如何使用了
可以在编译阶段就发现大部分错误,这总比在运行时候出错好
增强了编辑器和 IDE 的功能,包括代码补全、接口提示、跳转到定义、重构等
类型系统
TS最重要的类型系统,除了囊括了最基本的基础类型外,更引入了接口,类,泛型等
更多高级类型见:
https://www.tslang.cn/docs/ha...
基本类型
基本类型的变量申明和js没有太大区别,就是增加了类型的申明
let isDone: boolean = false; // 布尔型
let decLiteral: number = 6; // 浮点数
let name: string = "bob"; // 字符串
let sentence: string = `Hello, my name is ${ name }.` // 模板字符串
let unusable: void = undefined; // void表示空,可以是undefined 或者 null
let u: undefined = undefined; //undefined 类型的变量只能被赋值为 undefined
let n: null = null; //null 类型的变量只能被赋值为 null
需要注意的,声明一个 void 类型的变量没有什么用,因为你只能将它赋值为 undefined 和 null,与 void 的区别是,undefined 和 null 是所有类型的子类型。也就是说 undefined 类型的变量,可以赋值给 number 类型的变量
// 这样不会报错
let num: number = undefined;
// 这样也不会报错
let u: undefined;
let num: number = u;
数组
数组类型有多种定义方式
let list: number[] = [1, 2, 3]; //「类型 + 方括号」
let list: Array= [1, 2, 3]; //数组泛型 Array// 接口形式
interface NumberArray {
[index: number]: number;
}
let fibonacci: NumberArray = [1, 1, 2, 3, 5];
let list:(number | string)[] = [1, 2, 3,'4']; //联合类型的数组
let list: any[] = ['Xcat Liu', 25, { website: 'http://xcatliu.com' }]; // 允许数组中出现任何类型的any,不过这种数组原则上不算标准的数组。
需要注意,类数组不是数组类型,比如 arguments,NodeList等,所以无法使用数组类型来声明
任意值
任意值(Any)用来表示允许赋值为任意类型。类型系统的存在就是为了让变量在声明初就决定好自己的类型,如果是一个普通类型,在赋值过程中改变类型是不被允许的,但是 any 类型,则允许被赋值为任意类型(和js很像)
let aAnyNumber: any = '哈哈哈哈';
aAnyNumber = 2333;
类型推论
let x = 3;
//等价于
let x: number = 3;
//当需要从几个表达式中推断类型时候,会使用这些表达式的类型来推断出一个最合适的通用类型。例如,
let x = [0, 1, null];
//等价于
let x:number[] = [0, 1, null];
如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成 any 类型而完全不被类型检查
联合类型
联合类型(Union Types)表示取值可以为多种类型中的一种(类型的或概念),用|来划分
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
当 TypeScript 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型里共有的属性或方法:
function getLength(something: string | number): number {
return something.length;
}
//length 不是 string 和 number 的共有属性,所以会报错。
联合类型的变量在被赋值的时候,会根据类型推论的规则推断出一个类型:
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
console.log(myFavoriteNumber.length); // 5
myFavoriteNumber = 7;
console.log(myFavoriteNumber.length); // 编译时报错
//被赋值为string的 myFavoriteNumber类型 被推断成了 string,访问它的 length 属性不会报错。
//而重新被赋值为7的 myFavoriteNumber 的类型被推断成了 number,访问它的 length 属性时就报错了。
接口(interface)
与java的接口类似,它是对行为的抽象,声明一种类型的数据,而具体如何行动需要由类(classes)去实现。
TS中接口的作用就是为这些行为的抽象类型命名和为你的代码或第三方代码定义契约
interface IPerson {
name: string;
age: number;
}
let tom: IPerson = {
name: 'Tom',
age: 25
};
接口一般首字母大写,建议接口前可以加上I
正常情况声明的接口的里的变量都是必填,赋值的时候,变量的形状必须和接口的形状保持一致,不能多也不能少
interface IPerson {
name: string;
age: number;
}
let tom: IPerson = {
name: 'Tom'
};
//error
let tom: IPerson = {
name: 'Tom',
age: 25,
sex:'male'
};
//error
可选属性
当然,有时候接口里的属性不全都是必需的。 有些是只在某些条件下存在,或者根本不存在。这时候可以使用可选属性
interface IPerson {
name: string;
age?: number; //使用问号声明可选属性,可选属性的含义是该属性可以不存在。
}
let tom: IPerson = {
name: 'Tom'
};
任意属性
当我们能够确定这个对象还会带有任意数量的其它属性时,可以定义额外的属性
一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集
interface ISquareConfig {
color?: string;
width?: number;
[propName: string]: any;
}
//SquareConfig可以有任意数量的属性,并且只要它们不是color和width,那么就无所谓它们的类型是什么。
interface IPerson {
name: string;
age?: number;
[propName: string]: string;
}
//实际上上面一段代码会报错,类型“numbe