1、TypeScript 是 JavaScript 的一个超集,支持 ECMAScript 6 标准(ES6 教程)。
2、TypeScript 由微软开发的自由和开源的编程语言。
3、TypeScript 设计目标是开发大型应用,它可以编译成纯 JavaScript,编译出来的 JavaScript 可以运行在任何浏览器上。
JavaScript 与 TypeScript 的区别:
1、TypeScript 是 JavaScript 的超集,扩展了 JavaScript 的语法,因此现有的 JavaScript 代码可与 TypeScript 一起工作无需任何修改,TypeScript 通过类型注解提供编译时的静态类型检查。
2、TypeScript 可处理已有的 JavaScript 代码,并只对其中的 TypeScript 代码进行编译。
1、TypeScript作用域问题
// 如果我们在一个ts文件中添加了一个全局变量,那么在其他ts文件中就不能再去声明这个变量了// 例:1.tsconst a = 1232.tsconst a = '123'// 2.ts文件中就会报出,a已经声明过了,不能再声明// 解决办法:// 我们可以把2.ts作为一个模块导出,export {},因为模块是有单独作用域的,所以和1.ts文件不会产生冲突
2、Object类型
object类型并不是单只对象类型,而是泛指所有的非原始类型。也就是对象、数组、函数
// 例:const foo: object = // 可是是函数 function() {}、数组[]、对象{}// 如果要单独定义对象的话,可以使用const foo: {} = {}// 如果要单独针对对象里面的字段进行定义的话,可以使用const foo: {name: string, age: number} = { name: 'jack', age: 23 }// 注意:定义的对象必须要跟我们定义的变量的解构完全一致,否则会报错
3、数组类型
const foo: Array<number> = [1,2,3] // 表示定义一个数组中只能是数字的变量,其他会报错// 或const foo: number[] = [1,2,3]// 例子:计算一个数组的和,但是传的值必须是数字function sum(...args: number[]) { // 代表必须全部是由数字组成的数组类型return args.reduce((prev, current) => {return prev + current}, 0)}console.log(sum(1,2,3,4,5)) // 15
4、元组类型
明确元素数量以及每个元素类型的一个数组
// 例子:const arr: [name: string, age: number] = [name: 'jack', age: 23]// 这种就是元组类型
5、枚举类型
enum upOrDown {down = 0,up = 1}// 定义枚举// 或enum upOrDown {down,up}// 默认从0开始网上递增// 如果定义的值不是数字,那就必须的写上对应的值const goods = {name: '天猫精灵',price: 99,index: upOrDown.down // 0 未上架、1 已上架}// 通过upOrDown.dowm / upOrDown.up拿到对应的类型// 注意:枚举类型会影响到我们编译后的结果// 上面代码编译后对应的js文件会变成如下var upOrDown;(function (upOrDown) {upOrDown[upOrDown["down"] = 0] = "down";upOrDown[upOrDown["up"] = 1] = "up";})(upOrDown || (upOrDown = {}));const goods = {name: '天猫精灵',price: 99,index: upOrDown.down // 0 未上架、1 已上架};// 如果不想这样做的话我们可以定义 constconst enum upOrDown {down,up}// 编译后:const goods = {name: '天猫精灵',price: 99,index: 0 /* down */ // 0 未上架、1 已上架};
6、函数类型
// 函数定义的方式有两种:函数声明、函数表达式// 1、函数声明function foo(name: string, age: number): string {return `my name is ${name}, age ${age}`}foo('jack', 23)/*** 1、foo函数我们定义了两个参数,那么我调用foo方法的时候也必须传两个参数,不能多也不能少* 2、并且这两个参数我们分别定义了name必须为字符串类型,age必须为数字类型。如果我们传入的* 是其他类型也会报错* 3、我们还定义了返回值必须为string类型,如果返回的是其他类型也会报错* 4、如果我们定义可选参数可以在参数名后面加上'?',例子:age?: number。注意:可选参数必须定义在参数 * 的最后*/// 2、函数表达式const foo = function(name: string, age: number): string {return `my name is ${name}, age ${age}`}foo('jack', 23)/** 1、接受函数的这个变量也是有类型的,比如我们现这个函数返回的是一个字符串,那么这个foo变量应该就是* string类型* 2、如果我们在编辑器中写上函数的话,会提示const foo: (name: string, age: number) => string*/
7、任意类型(any)
any是动态类型可以接受任意的值,不会报任何语法上的错误,any是不安全的,所以不要轻易的去使用
function foo (value: any) {console.log(value)}foo(12)foo('string')foo(true)// 以上定义的any类型所有值都可以接受
8、隐式类型推断
隐式类型推断就是你在定义一个变量或者其他的时候,如果你没有给它定义类型,它会根据你的代码或者值推断出其类型
let age = 18/*** 比如你定义一个age = 18的变量,在编辑器中你会看到这样一个注解:let age: number* 意思就是定义了一个变量age,类型是number类型*/// 如果你将这个变量重新赋值,例:age = '123'// 这样的话编辑器中就会报:let age: number,不能将类型“string”分配给类型“number”。
9、类型断言(as)
类型断言的意思就是说:使用者非常确定我们定义的值是什么类型,但是代码并不确定。这个时候我们就可以使用断言的方式告诉代码,我们定义的是什么类型
const list = [1, 2, 3, 4, 5] // 定义一个变量全是数字的数组const res = list.find(i => i > 0) // 获取数组中第一个大于0的数字,返回的肯定是一个数字const result = res * res // 这个时候代码中会提示:const res: number | undefined,意思就是说res是个数字也有可能是 undefined,所以我们就不能是 * 来进行计算解决方法:使用断言的方式const num = res as number // 断言res一定是一个number类型const result = res * res // 这样计算就不会出现代码报错的问题
10、接口(interface)
接口就是用来约束一个对象的结构,一个对象去实现一个接口,那它就必须去拥有这个接口当中的所有成员,以及对应成员的类型
function foo (person) {console.log(person.name)console.log(person.age)}// 这个时候person就会报:(parameter) person: any// 这个时候我们可以给这个参数定义一个接口interface Person {name: stringage: number}function foo (person: Person) {console.log(person.name)console.log(person.age)}foo({name: 'jack',age: 23})/** 我们在调用这个方法的时候,就必须得传一个对象,这个对象就必须得包含name和age* 并且name是string类型,age是number类型,否则会报语法错误*/// 接口中还可以定义:可选成员、只读成员、动态成员// 可选成员:就是说我们定义的接口中字段可以有也可以是undefined,例:interface Person {name: stringage: numberwork?: string // 我们可以在work后面加一个 ? 来体现出我们这个字段是可选值}// 只读成员:就是说我们定义的字段是不能修改的interface Person {name: stringage: numberwork?: stringreadonly sex: string // 这个就是我们定义的成员只能读取,不能修改}// 动态成员:在我们不确定的情况我们可以定义动态成员interface Person {[key: string]: string // key就是我们定义的键,类型为string,后面的string是值的类型}const person: Person = {}这样我们就可以随意的想person对象中添加值person.name = 'jack'person.sex = '男'
11、类
描述:类就是一个具体事物的抽象特征,TypeScript中的类其实和js中的类差不多
// 1、基本使用class Person {name: stringage: number// 以上是和js的区别,我们如果要在构造函数中是this的话,必须在上面定义一个对应的值constructor(name: string, age: number) {this.name = namethis.age = age}sayHi(msg: string): void {console.log(`I am ${this.name}`)}}// 类的访问修饰符1、private(私有属性)class Person {name: stringprivate age: number // 如果我们在age上面定义了一个private私有属性的话,那这个age只能在类的内部去访问constructor(name: string, age: number) {this.name = namethis.age = age}sayHi(msg: string): void {console.log(`this is ${this.name}`)console.log(`this is ${this.age}`) // 可以访问到age属性}}const jack = new Person('name', 18)console.log(jack.name) // 可以访问到name属性console.log(jack.age) // 访问不到age属性2、public(公有属性)class Person {public name: string // 不加public默认就是public,建议添加,这样便于后期代码的可读性private age: number // 如果我们在age上面定义了一个private私有属性的话,那这个age只能在类的内部去访问constructor(name: string, age: number) {this.name = namethis.age = age}sayHi(msg: string): void {console.log(`this is ${this.name}`)console.log(`this is ${this.age}`) // 可以访问到age属性}}const jack = new Person('name', 18)console.log(jack.name) // 可以访问到name属性console.log(jack.age) // 访问不到age属性2、protected(受保护的)// 只能在子类中访问到,外部也是访问不到的,这是和private的区别class Person {public name: string // 不加public默认就是public,建议添加,这样便于后期代码的可读性private age: number // 如果我们在age上面定义了一个private私有属性的话,那这个age只能在类的内部去访问protected gender: trueconstructor(name: string, age: number) {this.name = namethis.age = agethis.gender = true}sayHi(msg: string): void {console.log(`this is ${this.name}`)console.log(`this is ${this.age}`) // 可以访问到age属性console.log(`this is ${this.gender}`) // 可以访问到gender属性}}class Student extends Person {constructor(name: string, age: number) {super(name, age)console.log(this.gender) // 能访问到gender属性}}const jack = new Person('name', 18)console.log(jack.name) // 可以访问到name属性console.log(jack.age) // 访问不到age属性console.log(jack.gender) // 访问不到gender属性注意:如果在构造函数上使用private方法,那这个类型就不能在外部被实例化class Student extends Person {private constructor(name: string, age: number) {super(name, age)console.log(this.gender)}}const tom = new Student() // 无法实例化解决方法:class Student extends Person {private constructor(name: string, age: number) {super(name, age)console.log(this.gender)}// 添加静态方式去返回这个实例对象static create (name: string, age: number) {return new Student(name, age)}}const tom = Student.create('tom', 18) // 这样就可以create静态方法去创建实例对象了
