文章目录
TypeScript 概述
TypeScript 基于 Javascript 基础之上的编程语言,是 JavaScript 的超集,或者叫扩展集。所谓超集就是在JavaScript 原有的基础上多了一些扩展特性,多出来的其实是一套更强大的类型系统,以及对 ECMAScript的新特性支持,它最终会编译成原始的 JavaScript。
因为TypeScript最终会编译成JavaScript去工作,所以任何一种Javascript运行环境都支持,例如我们传统的浏览器应用,或者是node应用,reactNative,桌面应用Electron,它们都可以使用TypeScript来开发。相比于Flow,TypeScript作为一门完整的编程语言,他的功能更为强大,生态也更健全、更完善。
一、快速上手&配置文件&标准库声明 (内置对象类型)&作用域问题
1.快速上手
-
安装
yarn add typescript --dev 安装完成之后在 node_modules/.bin 中 有一个 tsc
检查版本号:tsc -v -
编译转换
yarn tsc [文件名] 命令执行后会生成一个js文件
编译前
// text.ts (() => { const username: string = "迪西"; console.log(username); })();
编译后
// text.js (function () { var username = "迪西"; console.log(username); })();
注:1.使用 tsc 命令转js的时候一定要和前面的路径拼成你的Test.ts文件所在的路径 ,如上图所示 。否则就提示 error TS6053: File ‘Test.ts’ not found.
2. 如果没有其他的设置,再html中直接引入ts文件会报错,需要引入转换后的js文件
2.配置文件
tsc命令不仅仅可以去编译指定某个ts文件,它还可以去编译整个项目,编译整个工程。
- 创建 TypeScript 配置文件
yarn tsc --init
命令之后,会生成一个 tsconfig.json 文件。
- 常用的选项
- target:作用就是用设置编译过后 Javascript 所采用的 ECMA 标准;
- module:输出的代码采用什么样的方式去进行模块化;
- outDir:设置编译结果输出到的文件夹,一般我们会输出到 dist 文件夹;
- rootDir:配置我们源代码,也就是 Typescript 的代码所在的文件夹,一般我们会把源代码放在src目录;
- sourceMap:开启源代码映射,开启之后,调试的时候可以 sourceMap 文件进行调试源代码;
- strict:开启所有严格检查选项,严格模式下,需要我们对每一个成员都要指定明确的类型等等;
需要注意的是,如果我们还是使用 tsc 编译某个 ts 文件时,配置文件是不起作用的,只有当我们直接运行tsc命令去编译整个项目时,配置文件才生效。
3.标准库声明 (内置对象类型)
标准库就是内置对象所对应的声明,我们在代码中使用内置对象,就必须要引用对应的标准库,否则 typescript 就会找不到对应的类型,就会报错。
可通过配置文件lib选项添加我们要使用的标准库:
{
"compilerOptions": {
"lib": ["es2015", "DOM"]
}
}
4.作用域问题
不同文件可能会存在相同名称的变量,比如 a 文件定义了一个全局的变量 a,b文件也定义了一个全局变量 a,那么就会产生异常。
解决方法
- 用一个立即执行函数创建一个单独的作用域
(function () { const username: string = "迪西"; })()
- 使用export 导出,这样的话这个文件就会作为一个模块导出,模块有单独的模块作用域
const username: string = "迪西"; export {}
注: export后面的{ },是export 的语法,并不是表示导出一个空对象
当然,这样的一个问题在实际开发并不会用到,因为在绝大多数情况下,每个文件都会以模块的形式去工作。
二、基本类型
1.数字类型
数字类型,可以更精确地定义变量的值。数字类型可以包括整数和浮点数。
let age: number = 9;
let price: number = 29.99;
console.log(age); // 9
console.log(price); // 29.99
age = 10; // 正确
// price = "20.00"; // 错误,提示类型不匹配
2.字符串类型
字符串类型用于表示文本
let username: string = "迪西";
let greeting: string = 'Hello, 迪西!';
console.log(username); // 迪西
console.log(greeting); // Hello, 迪西!
// username = true; // 错误,类型不匹配
3.布尔类型
布尔类型在 TypeScript 中用于表示逻辑值 true 或 false。
let isDisabled: boolean = true;
let isOnly: boolean = false;
console.log(isDisabled); // true
console.log(isOnly); // false
// isDisabled = 1; // 错误,类型不匹配
4.数组类型
数组是一种容纳多个元素的数据结构,可以使用 number[] 或 Array<number> 来声明数字类型的数组。
// 使用元素类型 + [ ]
let usernames: string[] = ['迪西', '丁丁', '拉拉', '小波'];
// 使用 Array 泛型
let nums: Array<number> = [1, 2];
console.log(usernames); // ['迪西', '丁丁', '拉拉', '小波']
console.log(nums); // [1, 2]
5.元组类型
元组是一个明确元素数量以及每一个元素类型的数组。
元组是一种具有固定长度和特定类型的数组。.在 TypeScript 中,可以使用元组类型来定义。将不匹配类型的数组赋值给 元祖 将导致错误。
// 定义元组类型的方式:可类似数组字面量
let person: [string, number] = ['迪西', 11];
console.log(person); // ['迪西', 11]
// 访问元组当中元素的方式
//1. 可以使用数组下标的方式去访问
console.log(person[0]); // 迪西
console.log(person[1]); // 11
//1. 使用数组解构的方式去提取
const [age, name] = tuple
console.log(age, name) // 11 '迪西'
// person = ["丁丁", "13"]; // 错误,类型不匹配
元组一般用于一个函数中返回多个返回值
onst entries: [string, number][] = Object.entries({
foo: 12,
bar: 34
})
const [key, value] = entries[0]
// key => foo, value => 12
6.空和未定义
null 或 undefined,表示一个变量可能是空或未定义的状态
let mayNull: string | null = null;
let mayUndefined: number | undefined = undefined;
console.log(mayNull); // null
console.log(mayUndefined); // undefined
// mayNull = 23; // 错误,类型不匹配
7.任意类型
any 类型,不确定变量的类型,或者希望一个变量可以接受任何类型的值
any 类型,typescript 不会去做类型检查,仍然会存在类型安全的问题。所以不要轻易去使用这种类型。
let anyType: any = 42;
console.log(anyType); // 42
anyType = "嘻嘻";
console.log(anyType); // 嘻嘻
anyType = true;
console.log(anyType); // true
8.联合类型
联合类型, 允许变量具有多种类型之一,通过使用 | 运算符。
let unionType: string | number = "迪西"; // unionType字段可以是字符串或number, 若赋值boolean类型将提示类型不匹配
console.log(unionType); // 迪西
unionType = 42;
console.log(unionType); // 42
9.交叉类型
交叉类型,允许将多个类型合并为一个类型,通过使用 & 运算符。
interface Person {
name: string;
age: number;
}
interface likeTerms {
HobbiesSubject: () => void;
}
let autonomousCar: Person & likeTerms = { // & 它们合并成一个新的接口
name: "迪西",
age: 10,
HobbiesSubject: () => {
console.log("数学");
},
};
console.log(autonomousCar.name); // 迪西
autonomousCar.HobbiesSubject(); // 数学
10.object 类型(Object Types)
Typescript 中 Object 类型不单是指普通对象类型,它泛指所有的非原始类型,也就是对象,数组还有函数。
// 函数
const fn: object = function () {}
// 普通对象
const obj: object = {}
// 数组
const arr: object = []
如果需要普通对象类型,就要使用类似对象字面量的语法去标记类型,这种对象类型限制,它要求我们赋值对象的结果必须要跟我们标记类型的结构完全一致,不能多,也不能少。
const obj: { foo: number, str: string } = { foo: 123, str: '123' }
更好的方式是使用接口的方式,后面会有文章介绍!
11.函数类型(Function Types)
无非是对输入输出做限制,也就是参数和返回值。
- 函数声明的类型限制
-
基本用法
function func (a: number, b:number): number{ return a + b; } func(100, 200) // 注意:形参和实参个数要一致
-
可选参数
- 在参数后面加一个 ? 号
function func (a: number, b?:number): string { return 'func1' } func(100)
- 使用 es6,添加默认参数,因为添加默认值的参数就可有可无。
function func (a: number, b:number = 10): string { return 'func1' } func(100)
注:使用可选参数或者是默认参数,都必须要在参数列表的最后.
-
接收任意个数参数
使用 es6 的 … 操作符.function func (a: number, ...rest: number[]): string { return 'func1' } func(100, 200, 300, 400)
- 函数表达式的类型限制
函数表达式最终是放在一个变量上的,接收这个函数的变量,也是应该有类型的.
typescript一般会根据函数表达式推断出这个变量的类型const func = function (a: number, b: number): number{ return a + b; }
如果是把一个函数作为参数传递,也就是回调函数的方式,一般我们就会去约束我们这个回调函数形参的类型,使用类似箭头函数的方式去表示我们这个参数接收什么类型的函数,这种方式在定义接口的时候经常用到。const func: (a: number, b: number) => number = function (a: number, b: number): number { return a + b } console.log(func(10, 20)); // 30
12.泛型(Generics)
指的是我们去定义函数,接口,类的时候没有去定义具体类型,我们在使用的时候再去定义指定类型的这一种特征。
特点是极大程度的复用我们的代码。
-
不使用泛型:
// 定义一个创建 number 类型的方法 function createNumArray (length: number, value: number): number[] { const arr = Array<number>(length).fill(value) return arr } // 定义一个创建 string 类型的方法 function createStrArray (length: number, value: string): string[] { const arr = Array<string>(length).fill(value) return arr } const numArr = createNumArray (3, 100) const strArr = createStrArray (3, 'foo')
-
不使用泛型:
把类型用一个泛型参数 T 表示,把函数当中不明确类型用 T 去代表,在使用的时候再传递具体类型。如下:function createArray<T> (length: number, value: T): T[] { const arr = Array<T>(length).fill(value) return arr } const numArr = createArray<number>(3, 100) const strArr = createNumberArray<string>(3, 'foo')
其实 Array 是一个泛型类,在 typescript 中去定义这个 Array 类型时,它不知道我们使用它去存放什么样类型的数据,所以它就使用泛型参数,在我们去调用的时候再传入具体类型,这是一个泛型提现。
总的来说,泛型就是在我们定义的时候把不明确的类型,变成一个参数,在我们使用的时候再传递这样的一个类型参数。
二、类型注解
在 TypeScript 中,类型注解是提高代码可读性和稳健性的关键,
1.基础类型注解
let username: string = "John";
let age: number = 25;
let isStudent: boolean = false;
// username 为字符串类型 age为数字类型 isStudent 为布尔类型
2.数组和元组类型注解
数组和元组是 TypeScript 中常见的数据结构,在类型注解中,使用 number[] 表示数组,[string, number]表示元组。
// 元组类型
let person: [string, number] = ['迪西', 11];
console.log(person); // ['迪西', 11]
console.log(person[0]); // 迪西
console.log(person[1]); // 11
// person = ["Jane", "25"]; // 错误,类型不匹配
// 数组类型
let usernames: string[] = ['迪西', '丁丁', '拉拉', '小波'];
let nums: Array<number> = [1, 2];
console.log(usernames); // ['迪西', '丁丁', '拉拉', '小波']
console.log(nums); // [1, 2]
3.函数类型注解
函数类型注解为函数的参数和返回值明确类型,提高代码的可读性。
// 定义了add函数的参数和返回值类型
function add(x: number, y: number): number {
return x + y;
}
let result: number = add(3, 7);
4.对象类型注解
对象是 JavaScript 中最常见的数据结构之一,使用类型注解明确对象的结构。
let personInfo: { name: string; age: number } = {
name: "Alice",
age: 30,
};
5.联合类型和类型别名注解
通过联合类型和类型别名,使变量可以接受多种类型的值。
type Result = number | string;
function getResult(): Result {
return Math.random() > 0.5 ? "success" : 404;
}
6.Generics 类型注解
Generics(泛型) 是 TypeScript 中强大的能力,可以创建可重用的、灵活的代码。
function identity<T>(value: T): T {
return value;
}
let result0: number = identity<number>(9);
let result1: string = identity<string>('迪西');
console.log(result0, result1); // 9 '迪西'