一、贝唐 TypeScript
TypeScript 是 JavaScript 的两个嫩模齐,主要就提供更多了类别控制系统和对 ES6 的全力支持,它由 Microsoft 合作开发,标识符开放源码于 GitHub 上。
它的第二个版本正式发布于 2012 年 10 月,历经了数次预览后,那时已正式成为后端街道社区中不可忽视的精神力量,不但在 Microsoft 外部获得广为利用,所以 Google 合作开发的Angular从 2.0 已经开始就采用了 TypeScript 做为合作开发词汇,Vue 3.0 也采用 TypeScript 展开了解构。
TypeScript 是一类由谷歌合作开发的民主自由和开放源码的编程词汇。它是 JavaScript 的两个嫩模齐,所以本质上向那个词汇加进了较旧的动态类别和如前所述类的面向对象。
TypeScript 提供更多新一代的和急速产业发展的 JavaScript 优点,主要就包括这些源自 2015 年的 ECMAScript 和今后的决议案中的优点,比如说触发器机能和 Decorators,以协助创建强壮的模块。
二、自然环境构筑
自上而下加装tsC++:
npm install typescript -g
tsc -h // 查阅大部份指示
tsc -v // 查阅正式版
常用指示行句法:tsc [options] [file…]
tsc hello.ts
// 把指示的 .ts 文档载入 .js 文档。
tsc ./src/app.ts –outFile ./dist/app.js
手动窃听 ts文档变动并载入 js
tsc –rootDir ./src/* –outDir ./dist –watch
聚合 ts 工程项目指示行 tsconfig.json:
tsc –init
撰写 ts 指示行,选定 “rootDir”: “./src” 和 “outDir”: “./dist”,再次运行:
tsc –watch
三、五分钟入门 TypeScript
1、类别注解
TypeScript里的类别注解是一类轻量级的为函数或变量加进约束的方式。
let name:string = Jane
// string 是 person 函数的参数类别注解
function greet(person:string) {
return hello, +person
}
greet(Jane)
greet(name)
// Argument of type number is not assignable to parameter of type string.
greet(20)
// Expected 1 arguments, but got 0.
greet()
当你的 .ts 标识符里有错误,你仍然可以采用TypeScript,仍然可以顺利地被载入 .js 文档。但在这种情况下,TypeScript 会警告你标识符可能不会按预期执行。
2、接口
在TypeScript里,只在两个类别外部的结构兼容那么这两个类别就是兼容的。 这就允许我们在实现接口时候只要保证包含了接口要求的结构就可以,而不必明确地采用 implements语句。
// 定义两个接口
interface Person {
firstName: string,
lastName: string
}
function greet(p:Person) {
return `hello ${p.firstName} ${p.lastName}`
}
// 测试一下
let user = { firstName:zhang, lastName:san }
greet(user)
3、类
TypeScript全力支持JavaScript的新优点,比如说全力支持如前所述类的面向对象。让我们创建两个Student类,它带有两个构造函数和一些公共字段。 注意类和接口可以一起工作。
// 类
class Student {
public fullName =
constructor(public firstName, public lastName) {
this.fullName = `${firstName} ${lastName}`
}
}
// 接口
interface Person {
firstName: string,
lastName: string
}
// 类别注解
function greet(p:Person) {
return `hello ${p.firstName} ${p.lastName}`
}
// 测试一下
let user = new Student(zhang, san)
greet(user)
四、基本数据类别
TypeScript全力支持与JavaScript几乎相同的数据类别,此外还提供更多了实用的元组、枚举、any 和 void 等。
1、布尔、数字、字符串
// 布尔类别
let isBol: boolean = false
// 数字类型
let age: number = 20
// 字符串类别
let myname: string = zhangsan
myname = “li si”
let msg = `${myname}s age is ${age}`
2、数组、元组
// 数组(type[] 或 Array<type>)
let arr1: number[] = [1,2,3]
let arr2: string[] = [1,2,3]
let arr3: Array<number> = [4,5,6]
let arr4: Array<string[]> = [[1,2],[3,4]]
// 元组
// 元组类别允许表示两个已知元素数量和类别的数组,各元素的类别不必相同。当访问两个越界的元组元素时,会出现错误。
let x: [string, number, boolean] = [hello, 30, true]
console.log(x[0],x[1],x[2])
// x[3] = world // 报错
3、枚举类别
// 枚举
enum Cate {
office = 办公用品,
car = 汽车生活,
clothe = 男装女装,
sport = 户外运动,
book = 图书音像
}
let office_zh1 = Cate.office
console.log(enum, Cate)
4、any类别、void类别
// any类别
let noSure: any = 23.9
noSure = hello any
noSure = [1,2,3]
// let noSureArr: Array<any> = [hello, false, 23]
let noSureArr: any[] = [hello, false, 23]
// void类别,与any类别相反,它表示没有任何类别。
// 声明两个void类别的变量没有什么大用,因为你只能为它赋予undefined和null
let v1: void = undefined
let v2: void = null
// 当两个函数没有返回值时,你通常会见到其返回值类别是 void
function foo(arg:any): void {
console.log(该函数的返回值类别为void)
}
五、函数
1、函数声明
// 两个函数有输入和输出,要在 TypeScript 中对其展开约束
function sum(x: number, y: number): number {
return x + y
}
sum(1,2)
// 输入多余的(或者少于要求的)参数,是不被允许的
// sum(1)
// sum(1,2,3)
2、函数表达式
let sub = function(x: number, y: number): number {
return x – y
}
sub(10,5)
// 还可以采用接口的方式来定义两个函数需要符合的形状
interface SearchFunc {
(source: string, subStr: string): boolean
}
let search: SearchFunc = function(source: string, subStr: string) {
return source.search(subStr) !== -1
}
3、较旧参数
// 用 ? 表示较旧的参数,较旧参数必须接在必需参数后面,较旧参数后面不允许再出现必需参数了。
function foo(a: string, b?:string): string {
if(b) return a+b
return a
}
foo(hello)
foo(hello,world)
4、参数默认值
// TypeScript 会将加进了默认值的参数识别为较旧参数
// 此时,较旧参数不必一定要在必需参数后面
function bar(a:string=hello, b:string) {
return a +b
}
bar(undefined,world)
bar(hi, lisi)
5、剩余参数
中的剩余参数(rest 参数)
function push(arr:any[], …rest:any[]): any[] {
return […arr, …rest]
}
push([0], 1,2,3,4)
6、函数重载
function reverse(x: number): number
function reverse(x: string): string
function reverse(x: number | string): number | string {
if (typeof x === number) {
return Number(x.toString().split().reverse().join())
} else if (typeof x === string) {
return x.split().reverse().join()
}
}
// 我们重复定义了数次函数 reverse,前几次都是函数定义,最后一次是函数实现。
// TypeScript 会优先从最前面的函数定义已经开始匹配,所以多个函数定义如果有包含关系,需要优先把精确的定义写在前面。
reverse(100)
reverse(hello)
六、接口
什么是接口? 在面向对象词汇中,接口(Interfaces)是两个很重要的概念,它是对行为的抽象,而具体如何行动需要由类(classes)去实现(implement)。 TypeScript 中的接口是两个非常灵活的概念,除了可用于对类的一部分行为展开抽象以外,也常用于对「对象的形状(Shape)」展开描述。
在 TypeScript 中,我们采用接口(Interfaces)来定义对象的类别,如下示例:
interface Person {
name: string, // 必须属性
age: number, // 必须属性
mobile?: string, // 较旧属性
[propName: string]: any, // 任意属性
readonly role: number, // 只读属性
}
// 赋值的时候,变量的形状必须和接口的形状保持一致
let tom: Person = {
name: tom,
age: 30,
mobile: 110,
gender: male,
role: 1
}
注意1:采用 [propName: string] 定义了任意属性取 string 类别的值。一旦定义了任意属性,那么确定属性和较旧属性的类别都必须是它的类别的子集。注意2:只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候。
七、泛型
泛型(Generics)是指在定义函数、接口或类的时候,不预先选定具体的类别,而在采用的时候再选定类别的一类优点。
function print<T>(arg: T): void {
console.log(arg, arg)
}
print<string>(hello)
print<number>(100)
print<any>(1.2345)
function add<T>(x: T, y: T, z: T): void {
console.log(x, y, z)
}
add<number>(1,2,3)
add<string>(a,b,c)
add<any>(a,20,c)
1、全力支持采用多个泛型
function swap<T,U>(tup:[T,U]): [U,T] {
return [tup[1], tup[0]]
}
swap<number, string>([100, hello]) // [hello, 100]
interface MyU { a: string; b: number }
swap<boolean, MyU>([true, {a:hi,b:11}]) // [{a:hi,b:11}, true]
2、泛型约束
interface LengthType {
length: number
}
function printLength<T extends LengthType>(arg: T): number {
// 为什么要展开泛型约束呢?因为入参的数据类别不确定,它可能没有length属性
return arg.length
}
printLength<string>(hello) // 5
printLength<Array<any>>([1,2,a,b]) // 4
3、泛型类
class Dog<T> {
name: T
constructor(name: T) {
this.name = name
}
sayHi(): T {
return this.name
}
}
const dog = new Dog<string>(dahuang) // 调用constructor()
dog.sayHi()
4、泛型接口(泛型类别)
interface Tfn1<T> {
(x: T, y: T, z: T): T
}
const tf1: Tfn1<number> = function(x: number, y: number, z: number): number {
return x * y * z
}
tf1(1,2,3)
const tf3: Tfn1<string> = function(x: string, y: string, z: string): string {
return x + y + z
}
tf3(a,b,c)
interface Tfn2 {
<T>(x: T, y: T, z: T): void
}
const tf2: Tfn2 = <T>(x:T, y:T, z: T): void => {
console.log(x, y, z)
}
// const tf2: Tfn2 = function <T>(x:T, y:T, z: T):void {
// console.log(x, y, z)
// }
tf2<string>(a,b,c)
tf2<number>(10, 20, 30)