笔者是换了个工作这个公司使用的是react+typescript技术栈,笔者之前只是听过typescript,但是并没有去了解过,结果就导致了到公司有一点点崩溃。。可是后来经过了一个礼拜的学习感觉对typescript有了个初步的理解,后来又继续深入了解,现在突然想到应该还有很多朋友或许和笔者当时一样处于一种尴尬之地,所以笔者特意来博客写总结,帮助其他的朋友。
首先了解typescript是干什么的,有什么用。
typescript是javascript的超集,笔者认为就是约束javascript的,由于javascript是弱类型语言,所以很容易出一些未知的问题,比如说本来想要得到的数据是数组,可是最后却得到了一个对象,那么在这种时候你的代码是肯定有问题的。所以为了避免这样的情况发生,nodeJS之父就发明了typescript这个语言,用来约束数据类型的一种语言。这样就可以减少我们之前提过的想要的结果数据类型与真实接收到的数据类型不一致这个问题就解决了。大大减少了开发过程中的这类问题的出错率。当然代价就是需要学习这个语言。当然,如果你的js基础很好的话再加上了解过后端语言,那么typescript对你来说就特别特别轻松。
使用TypeScript
不管你想在什么项目当中用到它,你都需要全局安装typescript
npm install -g typescript
TypeScript的数据类型
- boolean(布尔值)
- number(数字)
- string(字符串)
- array(数组)
- object(对象)
- null和undefined(空的和未定义的)
- tuple(元祖)
- enum(枚举)
- any(任何)
- void(空的)
- never(永不存在的)
- 亦或者是类型断言,在后面会详细介绍。
前六个是和JavaScript一样的。可以转移至JavaScript数据类型详细介绍观看。
元祖类型:
元祖类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。比如,你可以定义一对值分别为string和number类型的元祖。
let x: [string, number];
x = ['hello',10]; //OK
x = [10,'hello']; //报错
当访问一个已知索引的元素,会得到正确的类型:
console.log(x[0].substr(1)); //OK
console.log(x[1].substr(1)); //error,'number' does not have 'substr'
当访问一个越界的元素,会使用联合类型替代:
x[3] = 'world'; //这是可以的,字符串可以赋值给(string | number)类型
console.log(x[5].toString()); //OK,‘string’和‘number’都有toString方法
x[6] = true; //Error,布尔不是(string | number)类型
联合类型是高级主题,我们会在以后的章节里讨论它。
枚举类型:
enum类型是对JavaScript标准数据类型的一个补充。像C#等其他语言一样,使用枚举类型可以为一组数值赋予友好的名字。
enum Color {Red, Green, Blue}
let c: Color = Color.Green;
或者全部采用手动赋值:
enum Color {Red = 1, Green = 2, Blue = 4}
let c: Color = Color.Green;
枚举类型提供的一个便利是你可以由枚举的值得到它的名字。例如,我们知道数值为2,但是不确定它映射到Color里的哪个名字,我们可以查找相应的名字:
enum Color {Red = 1, Green, Blue}
let colorName: string = Color[2];
console.log(colorName); //显示“Green”,因为上面代码里它的值是2。默认情况下值递增1,也可手动赋值
枚举常用于定义一个变量可能的值为哪些。
Any类型:
有时候,我们会想要为那些在编程阶段还不清楚类型的变量指定一个类型。 这些值可能来自于动态的内容,比如来自用户输入或第三方代码库。 这种情况下,我们不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。 那么我们可以使用 any类型来标记这些变量:
let notSure: any = 4;
notSure = 'hello world';
notSure = false;
这样就可以将notSure定义为任意类型的数据了。
在对现有代码进行改写的时候,any类型是十分有用的,它允许你在编译时可选择地包含或移除类型检查。 你可能认为 Object有相似的作用,就像它在其它语言中那样。 但是 Object类型的变量只是允许你给它赋任意值 - 但是却不能够在它上面调用任意的方法,即便它真的有这些方法:
let notSure: any = 4;
notSure.ifItExists(); //OK,ifItExists might exist at runtime
notSure.toFixed(); //OK, toFixed exists (but the compiler doesn't check)
let prettySure: Object = 4;
PrettySure.toFixed(); //Error:Property 'toFixed' doesn't exist on type 'Object'.
当你只知道一部分数据的类型时,any类型也是很有用的。比如,你有一个数组,它包含了不同类型的数据:
let list:any[] = [1,false,"hello"];
//也可以写成
let list:Array<any> = [1,false,'hello'];
list[1] = 100;
Void类型:
某种程度上来说,void类型像是与any类型相反,他表示没有任何类型。当一个函数没有返回值时,你通常会见到其返回值类型是void:
function warnUser(): void {
console.log('this is my warning message')
}
声名一个void类型的变量没有什么大用,因为你只能赋予undefined和null:
let unusable: void = undefined;
Never类型:
never类型表示的是那些永不存在的值的类型。例如,never类型是那些总是会抛出异常或根本就不会有返回值函数表达式或箭头函数表达式的返回值类型;变量也可以是never类型,当他们被永不为真的类型保护所约束时。
never类型是任何类型的子类型,也可以赋值给任何类型;然而,没有类型是never的子类型或可以赋值给never类型(除了never本身之外)。即使any也不可以赋值给never。
下面是一些返回never类型的函数:
//返回never的函数必须存在无法达到的终点
function error(message: string): never {
throw new Error(message);
}
//推断的返回值类型为never
function fail() {
return error('something failed');
}
//返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
while (true) {
}
}
类型断言:
有时候你会遇到这样的情况,你会比TypeScript更了解某个值的详细信息。通常这会发生在你清楚的知道一个实体具有比它现有类型更确切的类型。
通过类型断言这种方式可以告诉编辑器,“相信我,我知道自己在干什么”。类型断言好比其他语言里的类型转换,但是不进行特殊的数据检查和结构。它没有运行时的影响,只是在编译阶段起作用。TypeScript会假设你,程序员,已经进行了必须的检查。
类型断言有俩种形式。其一是"尖角号"的写法:
let someValue: any = 'this is a string';
let strLength: number = (<string>someValue).length;
另一个为as语法:
let someValue: any = 'this is a message';
let strLength: number = (someValue as string).length;
俩种形式是等价的。至于使用哪个大多数情况下是凭个人喜好;笔者由于最开始的项目就是react结合typescript的项目,在JSX语法里只有as语法断言是被允许的,所以笔者是比较习惯写as语法的。
使用时机:
- 定义变量的时候
let a: string = 'hello world';
- 定义函数参数的时候
function a(b: number) {
}
- 定义函数返回值的时候
function a(): boolean {
return true;
}
TypeScript的基本数据类型就到这里就已经基本学完了,可以学习下一章节了。
下一章节请移步至TypeScript入门(2)观看
下一节主讲内容为TypeScript的接口定义。