(1)编译开发TS可以使用
(2)数据类型
数据类型主要作用是:方便数据维护和数据校验;
布尔类型 boolean
数字类型 number
字符串类型 string
数组类型 array
元组类型 tuple
枚举类型 enum
任意类型 any
null 和 undefined
void类型
never类型
数组的三种写法:
var arr:number[] = [11,22,33];
console.log(arr);
var arr:Arrary<number> =[11,22,33];
console.log(arr);
var arr:any[] =['1yhuyhub1',22,33,true];
console.log(arr);
元祖类型
var arr:[string,number] =['1yhuyhub1',22];
console.log(arr);
枚举类型
enum Flag = {success =11; error=2}
let s:Flag = Flag.success;
console.log(s); //11
enum Color = {blue,red,success =1; error=2}
let c:Color = Color.blue;
console.log(c); //1
没有类型如果没有赋值,则打印的就是下标;
任意类型
任意类型可以解决很多问题,比如处理元素节点;
如上图,如果使用Object类型会报错,使用any类型就不会报错了~
null 和 undefined
null
和 undefined
是其他类型(never)的子类型;
正确的使用方法
如果没有值的话,可以同时定义一个当前类型和其他的null
或者undefined
类型
如上图,定义未赋值 或者 定义赋值都不会报错;
void类型
void表示没有任何类型,一般用于定义方法的时候没有返回值
有返回值的话,要指定返回值类型
function run():number{
return 123
}
run()
never类型
never
类型表示的是那些永不存在的值的类型。 例如, never
类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型; 变量也可能是 never
类型,当它们被永不为真的类型保护所约束时。
never
类型是任何类型的子类型,也可以赋值给任何类型;然而,没有类型是never
的子类型或可以赋值给never
类型(除了never
本身之外)。 即使 any
也不可以赋值给never
。
var a:never;
a=(()=>{
throw new Error('错误');
})()
(3)ts函数
原始ES5写法
TS 写法:声明 和 匿名函数两种
函数声明
function run():string{
return 'ni shi haoren'
}
匿名函数
var fun2 = function():string{
return 'ni shi haoren'
}
定义传参
function run(name:string,age:number):string{
return `${name}---${age}`
}
run('zhangsan',34);
//-----或者-------
var func2 = function(name:string,age:number):string{
return `${name}---${age}`
}
run2('zhangsan',34);
// -------没有返回值的函数-----
function run(name:string,age:number):void{
console.log(`${name}---${age}`)
}
TS中的形参
- 可以选参数 ES5 中的形参和实参可以不一致,但是在ts中必须一样;
- 如果不一样就需要配置可选参数;
- 可选参数必须配置到最后;
function getInfo(name:string,age?:number):string{
if(age){
return `${name}---${age}`
}else{
return `${name}---`
}
}
getInfo('zhansan',9999);
可选参数后面使用问号表示;
默认参数
function getInfo(name:string,age:number=20):string{
if(age){
return `${name}---${age}`
}else{
return `${name}---`
}
}
getInfo('zhansan',9999);
剩余参数
举例说明
使用剩余参数后
function sum(...result:number[]):number{
let sum = 0;
for(let i=0;i<result.length;i++){
sum+=result[i];
}
return sum;
}
sum(1,2,3,4);
如果使用多个参数,且包含剩余参数的函数
剩余参数必须放到最后面;
ts函数重载
Java
中的方法重载,指的是两个或者两个以上同名的函数,但是它们的参数是不一样的,这时候就会出现函数重载;
typescript
中的重载,通过一个函数提供多个函数类型定义来实现重载;
ES5
中出现同名的方法,下面的会替换上面的方法;
TS中的实现
也存在参数可选的情况下重载
箭头函数
箭头函数的this,始终指向上下文的实例;
(4)类
ES5的类
function Person{
this.name = 'zhansan';
this.age = 20;
}
var p = new Person();
console.log(p.name);
ES5构造函数 和 原型链 里面增加方法
function Person{
this.name = 'zhansan';
this.age = 20;
this.run = function(){
console.log(this.name);
}
}
Person.prototype.sex = 'man';
Person.prototype.work = function(){
console.log(this.name + "在工作");
}
var p = new Person();
p.work();
如上图:原型链上面的方法可以背实例共享,但是构造函数的不会;
ES5增加静态方法
function Person{
this.name = 'zhansan';
this.age = 20;
this.run = function(){
console.log(this.name);
}
}
Person.getInfo = function(){
console.log("23456789);
};
// 使用静态方法
Person.getInfo();
(5)继承
ES5继承----对象冒充继承
function Person{
this.name = 'zhansan';
this.age = 20;
this.run = function(){
console.log(this.name);
}
}
Person.prototype.sex = 'man';
Person.prototype.work = function(){
console.log(this.name + "在工作");
}
//定义一个其他方法
function Dog(){
Person.call(this);
}
//使用继承的方法
var p = new Dog();
p.run();
// p.work(); 不可以
继承的实现: 对象冒充可以继承构造函数里面的属性和方法,但是不能继承 原型链的方法;
ES5继承----原型链继承
function Person{
this.name = 'zhansan';
this.age = 20;
this.run = function(){
console.log(this.name);
}
}
Person.prototype.sex = 'man';
Person.prototype.work = function(){
console.log(this.name + "在工作");
}
//定义一个其他方法
function Dog(){
console.log('我是好人’);
}
//使用继承的方法
Dog.prototype = new Person();
var dog = new Dog();
dog.work();
dog.run();
原型链的问题:实例化的时候 没法给父类传参;
ES5继承----原型链+构造函数 继承
function Person{
this.name = 'zhansan';
this.age = 20;
this.run = function(){
console.log(this.name);
}
}
Person.prototype.sex = 'man';
Person.prototype.work = function(){
console.log(this.name + "在工作");
}
//定义一个其他方法
function Dog(name, age){
Person.call(this,name,age);
}
//使用继承的方法
Dog.prototype = new Person();
var dog = new Dog('zhangsan',89);
dog.work();
dog.run();
组合继承可以实现上面两种方式都使用的功能;
TS里面定义类
class Person{
name:string;
construct(n:string){ // 实例化的时候会触发construct
this.name = n;
}
run():void{
console.log(this.name);
}
}
var p = new Person('zhansan');
p.run();
TS里面的继承
ts中如何实现继承 (extends / super)
class Person{
name:string;
construct(n:string){ // 实例化的时候会触发construct
this.name = n;
}
run():void{
console.log(this.name);
}
}
class Dog extends Person{
construct(n:string){
super(name); //构造函数和super都要有;super 相当于 调用父类的构造函数
}
}
var p = new Dog('zhansan');
p.run();
继承这里明显的ts比js要简单;
(6)类里面的修饰符
举例:private
的使用
子类 和 类外部 都无法使用,只能在当前类 内部使用;
举例:private
的使用
(7)静态属性 与 静态方法
ES5的 静态属性 和 静态方法
静态属性 和 静态方法都是直接绑定在函数上面的,实例属性和实例方法都是在函数内部的;
TS的 静态属性 和 静态方法
class Person{
public name:string;
public age:number = 20;
constructor(name:string){
this.name = name;
}
run(){ // 实例方法
console.log(this.name + "123456");
}
work(){ // 实例方法
console.log(this.name+"098765");
}
static print(){ // 静态方法
console.log(this.name+"098765-"+ this.age);
}
}
var p = new Person();
p.run(); // 使用实例方法
Person.print(); //使用静态方法
1- 实例方法 必须在外部实例化以后才能使用;
2- 实例方法 前面加上static 就会变成静态方法;
3- 静态方法不能使用基本属性,只能使用静态属性;
多态
父类定义一个方法不去实现,让继承它的子类去实现,每个子类都有不同的表现;
(8)抽象方法
(1)抽象类
标准:一个类要求它的字类必须包含指定方法,它是提供其他类继承的基类,不能被直接实例化。
定义抽象类:
abstract class Animal {
abstract eat():any ;
}
let a=new Animal(); // 报错:无法创建抽象类的实例
(2)抽象方法
抽象方法在子类里面必须实现
// 父类
abstract class Animal {
public name: string;
constructor(name: string) {
this.name = name;
}
abstract eat(): any;
}
// 子类Dog
class Dog extends Animal {
constructor(name: string) {
super(name);
}
// 抽象类的子类必须实现抽象类里面的抽象方法
eat() {
console.log(this.name + '在吃肉');
}
}
let d = new Dog('达摩');
d.eat();
// 子类Cat
class Cat extends Animal {
constructor(name: string) {
super(name);
}
}
子类Cat不实现eat()方法,会报错:非抽象类“Cat”不会实现继承自“Animal”类的抽象成员“eat”,即子类Cat不会自动继承父类的方法
注意点:
(9)接口
另一个我觉得还不错的解释;
定义方法:
function print():void{
console.log('12345678');
}
print();
定义方法(参数限定):
function print(label:string):void{
console.log('12345678');
}
print();
定义方法(JSON参数限定):
接口实现:
作用:对批量方法传入参数进行约束;
interface FullName{
first:string, // 接口属性
second:string
}
function name(name:FullName){
console.log(name.first + ''----"+ name.second);
}
// name('23456'); 错误写法
var obj = { //必须传入 first,second
age:20,
first:'zhangsan',
second:'siwu'
}
name(obj);
传入的对象必须包含接口需要实现的参数;
接口批量实现:
接口可选参数:
1、实现接口的参数的顺序可以不同,但是必须要有;
2、可选的参数后面带一个问号,表示参数可以传可以不传;
模拟ajax
定义一个接口:
实现这个接口:
调用接口:
(9)函数型接口
作用:对方法传入的参数,以及返回值进行约束;
interface encrypt{
(key:string,value:string):string
}
var md5:encrypt = function(key:string,value:string):string{
return key+value
}
md5('name','zhangsan');
举例: 两种加密方式
(10)可索引接口
可索引接口,是数组,对象的约束(不常用)
索引必须是number
interface User{
[index:number]:string
}
var arr:User = ['aa','bb'];
console.log(arr[0]);
索引必须是string
interface User{
[index:string]:string
}
var arr:User = {name:'zhangsan'};
(11)类类型接口
对类的约束 和 抽象类有点像
方法必须实现,但是参数也可以不传;
(12)接口拓展
接口可以继承接口
interface Animal{
eat():void;
}
interface Dog entends Animal{
work():void;
}
class Preson implements Dog{
public name:string;
construtor(name:string){
this.name = name;
}
eat(){
}
work(){
}
}
实现一个继承类和继承接口同步的
(13)泛型函数
泛型: 可以支持不特定的数据类型; 要求:传入的参数和返回的参数一致;
举例:只能返回string类型
方法一:
使用any可以实现,但是相当于放弃了类型检查;
上面可以返回 string,和 number;
第二种:使用泛型
传入的参数和返回的参数一致;
// T表示范型,具体是什么类型是调用这个方法的时候决定的
function getData<T>(value:T):T{
return value;
}
getData<number>(123);
这里 可以使用T
也可以使用别的字符串,但是必须保证三个一致
;
返回类型可以是任意类型实现
将返回值的类型设置成any即可;
(14)泛型类
举例:比如有一个算法,需要同时支持返回数字和返回字符串两种类型,就可以通过范型类来实现;
如上面所示只能返回一种类型;
使用范型类
(15)泛型接口
先看看函数类型接口
第一种:
第二种:
本人更喜欢第一种模式;
(16)泛型类
使用JS写法
使用普通类
使用范型类
(17)TS模块
举例实现:
1、创建数据库
也可以使用另一种暴露方式
2、调用数据库的内容
(18)命名空间
命名空间里面的方法要使用,必须暴露出去;
调用命名空间的方法
访问多个命名空间
(19)装饰器
(20)类装饰器
传递的参数params就是当前的类;
如上图:举例拓展一个属性,在这类的基础上拓展一个apiUrl属性;还可以拓展方法,如下图
拓展类传递参数:
如上图所以:target
代表要装饰的类,params
代表装饰器传递的参数;
在装饰器里面拓展原始类的属性
类装饰器的构造函数
修改构造函数 的数据
如果loginClass
爆红 是因为getData()
没有重载;
(21)属性装饰器
修改属性的值
(22)方法修饰器
举例测试拓展类
修改当前方法
(23)方法参数修饰器