导航
TypeSeript 简称 TS
TS 和 JS 之间的关系其实就是 Less/Sass
和 CSS
之间的关系
就像 Less/Sass
是对 CSS
进行扩展一样,TS 也是对 JS 进行扩展
就像 Less/Sass
最终会转换成 CSS
一样,我们编写好的 TS 代码最终也会换成 JS
因为 JavaScript 是弱类型,很多错误只有在运行时才会被发现
而 TypeScript 是强类型,它提供了一套静态检测机制,可以帮助我们在编译时就发现错误
支持最新的 JavaScript 新特特性
支持代码静态检查
支持诸如 C,C++,Java,Go 等后端语言中的特性
(枚举、泛型、类型转换、命名空间、声明文件、类、接口等)
npm install typescript -g # 全局安装
tsc demo.ts # 编译ts文件为js文件
TypeScript支持与JavaScript几乎相同的数据类型,此外还提供了实用的枚举类型方便我们使用
// 数值类型number
let val: number; // 定义了一个名称叫做 val 的变量,这个变量中将来只能存储数值类型的数据
val = 123;
// val = '123'; // 报错
// 注意点:其它的用法和JS一样
// val = 0x11;
console.log(val);
let val: boolean;
val = true;
// val = 1; // 报错
let val: string;
val = '123';
val = `val=${val}`;
// 方式一
let arr1: Array<number>;
arr1 = [1, 3, 5];
// arr1 = ['a', 3, 5]; // 报错
// 方式二
let arr2: string[];
arr2 = ['a', 'b', 'c'];
// arr2 = ['a', 1, 'c']; // 报错
let arr3: (number | string)[];
// or let arr3: Array<string | number>;
arr3 = [1, 'b', 2, 'c'];
let arr4: any[];
arr4 = [1, 'b', 'false'];
TS 中的元祖类型其实就是数组类型的扩展 元相用于保存定长定数据类型的数据
let arr5: [string, number, boolean];
arr5 = ['a', 1, true];
枚举类型是 TS 为 JS 扩展的一种类型,在原生的JS中是没有枚举类型的
枚举用于表示固定的几个取值
例如:一年只有四季、人的性别只能是男或者女
enum Gender {
Male,
Female
}
let val: Gender;
val = Gender.Male;
val = Gender.Female;
// val = 'nan'; // 报错
// val = false'; // 报错
// 注意点:TS中的枚举底层实现的本质其实就是数值类型,所以赋值一个数值不会报错
val = 666; // 不会报错
console.log(Gender.Male); // 0
console.log(Gender.Female); // 1
enum Gender {
Male: 6,
Female
}
// 注意点:TS中的枚举类型的取值,默认是从上至下从0开始递增的
虽然默认是从0开始递增的,但是我们也可以手动的指定枚举的取值的值
// 注意点:如果手动指定了前面枚举值的取值,那么后面枚举值的取值会根据前面的值来递增
console.log(Gender.Male); // 6
console.log(Gender.Female); // 7
enum Gender {
Male,
Female = 6
}
// 注意点:如果手动指定了后面枚举值的取值,那么前面枚举值的取值不会受到影响
console.log(Gender.Male); // 0
console.log(Gender.Female); // 6
enum Gender {
Male = 8,
Female = 6
}
// 注意点:我们还可以同时修改多个枚举值的取值,如果同时修改了多个,那么修改的是什么最后就是什么
console.log(Gender.Male); // 8
console.log(Gender.Female); // 6
// 我们可以通过枚举值拿到它对应的数字
console.log(Gender.Male); // 0
//我们还可以通过它对应的数据拿到它的枚举值
console.log(Gender[0]); // Male
var Gender;
(function (Gender) {
// Gender[key] = value;
Gender[Gender["Male"] = 0] = "Male";
Gender[Gender["Female"] = 1] = "Female";
})(Gender || (Gender = {}));
Gender[Gender['male'] = 0]
就是把 Gender['male'] = 0
的结果 0
赋值给了 Gender
对象
Gender[0] = 'Male'
let Gender = {};
Gender["Male"] = 0;
Gender[0] = "Male";
Gender["Female"] = 1;
Gender[1] = "Female";
// 其实是给 Gender 对象添加了4个属性
数字枚举的取值默认从0开始递增
数字枚举的取值可以是字面量,也可以是常量,也可以是计算的结果
const init = 666;
const getNum = (): number => {
return 888;
}
enum Gender {
// Male,
// Male = 66,
// Male = init, // 注意点:如果使用常量给前面的枚举值赋值了,那么后面的枚举值也需要手动的赋值
// Female = 9
Male = getNum(), // 注意点:如果使用计算结果给前面的枚举值赋值了,那么后面的枚举值也需要手动的赋值
Female = 999
}
console.log(Gender.Male);
console.log(Gender.Female);
如果使用字符串给前面的枚举值赋值了,那么后面的枚举值也必须手动赋值
enum Gender {
Male = 'Lance',
Female = 'Linda' // 如果使用字符串给前面的枚举值赋值了,那么后面的枚举值也必须手动赋值
}
console.log(Gender.Male);
console.log(Gender.Female);
和数字枚举不一样,字符串枚举不能使用常量或者计算结果给枚举值赋值
虽然字符串枚举不能够使用常量或者计算结果给枚举值赋值,但是它可以使用内部的其它枚举值来赋值
enum Gender {
Male = 'Lance',
Female = 'Linda',
Yao = Male
}
console.log(Gender.Male);
console.log(Gender.Female);
console.log(Gender.Yao);
可以根据枚举值获取到原始值也可以根据原始值获取到枚举值
enum Gender {
Male,
Female
}
console.log(Gender[0]); // 'Male'
console.log(Gender[1]); // 'Female'
枚举中既包含数字又包含字符串,我们就称之为异构枚举
enum Gender {
Male = 233,
Female = 'Linda',
}
console.log(Gender.Male);
console.log(Gender.Female);
注意点:如果是字符串枚举,那么无法通过原始值获取到枚举值
enum Gender {
Male = 233,
Female = 'Linda',
}
console.log(Gender.Male);
console.log(Gender.Female);
console.log(Gender[6]);
// console.log(Gender['Linda']); // 报错
console.log(Gender);
我们可以把枚举成员当做类型来使用
enum Gender {
Male,
Female,
}
interface ITest {
type: Gender.Male
}
class Person implements ITest {
// type: Gender.Male = 0; // 正确
// type: Gender.Female = 0; // 由于类型不匹配,报错
type = 1; // 注意点:由于数字枚举的本质就是数值,所以这里写一个数值也不会报错
}
enum Gender {
Male = 'Lance',
Female = 'Linda',
}
interface ITest {
type: Gender.Male
}
class Person implements ITest {
// type: Gender.Male = Gender.Male; // 正确
// type: Gender.Female = Gender.Female; // 由于类型不匹配,报错
type: 'Lance'; // 注意点:如果是字符串枚举,那么只能是枚举成员的值,不能是其它的值
}
我们可以把枚举类型当做一个联合类型来使用
enum Gender {
Male = 'Lance',
Female = 'Linda',
}
interface ITest {
type: Gender; // 变成联合枚举类型了 age:(Gender.Male | Gender.Female)
}
class Person implements ITest {
type: Gender.Male = Gender.Male
}
枚举在编译之后是一个真实存储的对象,所以可以在运行时使用 而像接口这种只是用来做约束做静态检查的代码,编译之后是不存在的
普通枚举和常量枚举的区别:
常量枚举好处:
enum Gender1 {
Male,
Female,
}
console.log(Gender1.Male === 0);
const enum Gender2 {
Male,
Female,
}
console.log(Gender2.Male === 0);
结果区别:
any 表示任意类型,当我们不清楚某个值的具体类型的时候我们就可以使用 any
一般用于定义一些通用性比较强的变量,或者用于保存从其它框架中获取的不确定类型的值
在 TS 中任何数据类型的值都可以负责给 any 类型
let value: any;
value = 'abc';
value = 123;
value = true;
value = [1, 3, 5];
void 与 any 止好相反,表示役有任何类型,一股用于函数返回值
在 TS 中只有 null 和 undefined 可以赋值给 void 类型
function test(): void {
console.log('Hello world');
}
表示的是那些永不存在的值的类型
一般用于抛出异常或根本不可能有返回值的函数
function demo(): never {
throw new Error('出错了');
}
demo();
function demo2(): never {
while (true);
}
demo2();
表示一个对象
let obj: object;
// obj = 1; // 报错
// obj = '123'; // 报错
obj = { name:'Lance', age: 23 };
console.log(obj);
TS中的类型断言和其它编程语言的类型转换很像,可以将一种类型强制转换成另外一种类型
类型断言就是告诉编译器,你不要帮我们检查了,相信我,我知道自己在干什么。
例如:我们拿到了一个 any 类型的变量,但是我们明确的知道这个变量中保存的是字符串类型
let str: any = 'lance';
// 方式一
let len (<string>str).length;
// 方式二
// 注意点:在企业开发中推荐使用as来进行类型转换(类型断言)
// 因为第一种方式有兼容性问题,在使用到了JSX的时候兼容性不是很好
let len (str as string).length;
console.log(len);
和 number, string, boolean, enun 这些数据类型一样
接口也是一种类型,也是用来约束使用者的
interface IFullName {
firstName: string
lastName: string
}
let lance: IFullName = {
firstName: 'Lance',
lastName: 'Yang'
}
function say({ firstName, lastName }: IFullName): void {
console.log(`我的姓名是:${firstName}_${lastName}`);
}
say(lance);
// 注意点:如果使用接口来限定了变量或者形参,那么在给变量或者形参赋值的时候,
// 赋予的值就必须和接口限定的一模一样才可以,多一个或者少一个都不行
say({ firstName: 'Jonathan' }); // 报错
say({ firstName: Jonathan', lastName: Lee', middleName: "666" });// 报错