简介
- typeScript是什么:typeScript是js的超集
- 特点:提供类的类型和es6的支持
- 优点:
- 增加代码的可读性和可维护性以及兼容性
- 类型系统是最好的文档
- 在编译阶段就发现错误,比运行时发现错误好
- 增加了编辑器和ide的功能,代码不全、接口提示、跳转到定义、重构
- js文件可重命名为.ts文件
- 不显式的定义类型,也能自动作出类型推论
- 可定义一切类型 即使typescript编译报错,也可生成js文件 兼容第三方库,即使第三方库不是用typeScript写的,也可编写单独的类型文件供typeScript读取
- 缺点:
- 集成到构建流程需要工作量,可能和一些库结合的不是很完美
- 安装: npm i -g typescript 执行tsc ts文件来编译会生成js文件或者ide支持
数据类型
数据类型主要作用是:方便数据维护和数据校验
布尔类型 boolean
数字类型 number
字符串类型 string
任意js对象 Object
写法: let a: {name:string}
let a:{name:string,age?:number} ,问号表示可选值
let a:{name:string,[propName:string]:any},不限制其它属性
let a:(a:number,b:number)=>number
数组类型 array
写法:var arr:Arrary<number> =[11,22,33];
var arr:number[] = [11,22,33];
var arr:any[] =['1yhuyhub1',22,33,true];
元组类型 tuple (固定长度数组)
写法:let a:[string,string]
枚举类型 enum
写法:enum Flag = {success =11; error=2} let s:Flag = Flag.success;
任意类型 any
写法:function par(): void { console.log('par') }
类型安全的any unknown
没有值或undefined void
不能是任何值 never
写法:var a:never; a=(()=>{ throw new Error('错误'); })()
类型断言,告诉解析器变量的实际类型
a=b as string
a=<string>b
与,或
let a:{name:string}&{age:number},a={name:'大帅比',age:18}
let a:'男' | '女'
类型别名
只能声明一个
type mgType=1|2|3,let a:myType,type a{name:string,age:number}
接口
- 只能定义对象
- 可以重复声明
- 定义类的时候可以限制结构
(function() {
// 描述一个对象的类型(别名形式)
type myType = {
name: string,
age: number
}
// type myType = {} // 报错 重复声明
/**
* 接口用来定义一个类结构,用来定义一个类中应该包含哪些属性和方法
* 接口也可用来当成类型声明去使用
*
* 接口可重复声明
*/
interface myInterface {
name: string,
age: number
}
interface myInterface {
gender: string
}
const obj: myInterface = {
name: '哈哈哈',
age: 12,
gender: '男'
}
/**
* 接口可以在定义类的时候限制类的结构
* 接口中的所有属性都不能有实际的值
* 接口只定义类的结构 而不考虑实际值
*/
interface myInter {
name: string;
sayHello(): void;
}
/**
* 定义类时,可以使类去实现一个接口
* 实现接口就是使类满足接口的要求
*
*/
class MyClass implements myInter {
name: string;
// 需要写构造函数 给name赋值
constructor(name: string) {
this.name = name;
}
sayHello() {
console.log('大家好');
}
}
const m = new MyClass('嘻嘻');
m.sayHello(); // 大家好
console.log(m); // MyClass {name: "嘻嘻"}
})();
// 编译后的js
"use strict";
(function () {
const obj = {
name: '哈哈哈',
age: 12,
gender: '男'
};
/**
* 定义类时,可以使类去实现一个接口
* 实现接口就是使类满足接口的要求
*
*/
class MyClass {
// 需要写构造函数 给name赋值
constructor(name) {
this.name = name;
}
sayHello() {
console.log('大家好');
}
}
const m = new MyClass('嘻嘻');
m.sayHello();
console.log(m);
})();
继承
抽取公共属性或者函数,用作继续的父级
(function() {
// 定义animal类
class Animal {
name: string;
age: number;
// constructor 构造函数 构造函数会在对象创建时调用(默认调用)
constructor(name: string, age: number) {
// 在实例方法中 this表示当前的实例
// 可以通过this向新建的对象中添加属性
this.name = name;
this.age = age;
}
sayHello() {
console.log('动物在叫~');
}
}
/**
* 此时 Animal 被称为为父类 Dog、Cat 被称为子类
* 使用继承后 子类将会拥有父类的所有方法和属性
* 如果在子类中添加了和父类的相同的方法 则子类方法会覆盖父类的方法
*/
// 定义狗的类 继承Animal类
class Dog extends Animal {
run() {
console.log(`${this.name}在跑路~~~`);
}
sayHello() {
console.log('汪汪汪');
}
}
// 定义猫的类 继承Animal类
class Cat extends Animal {
}
const dog = new Dog('小黑', 3);
const cat = new Dog('咪咪', 2);
console.log(dog); // Dog {name: "小黑", age: 3}
dog.sayHello(); // 汪汪汪
dog.run(); // 小黑在跑路~~~
console.log(cat); //Dog {name: "咪咪", age: 2}
cat.sayHello(); // 动物在叫~
cat.run(); // 报错
})();
super
super即调用父级对象内容
// 超类
(function() {
// 定义animal类
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
sayHello() {
console.log('动物在叫~');
}
}
class Dog extends Animal {
age: number;
constructor(name: string, age: number) {
// 如果在子类中写了构造函数 在子类函数中必须对父类的构造函数进行调用
super(name); // 调用父类的构造函数
this.age = age;
}
sayHello() {
// 在类的方法中 super表示当前类的父类
//super.sayHello();
console.log('汪汪汪');
}
}
const dog = new Dog('小黑', 2);
dog.sayHello(); // 汪汪汪
console.log(dog); // Dog {name: "小黑", age: 2}
})();
抽象类
- abstrict 一个class,抽象类不能实例化,只能继承
(function() {
// 定义animal类
/**
* 以abstract开头的类是抽象类
* 抽象类与其他类区别不大 只是不能用来创建对象
* 抽象类就是专门用来继承的类
*
* 抽象类中可以添加抽象方法
*/
abstract class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
// 抽象方法使用abstract开头 没有方法体
// 抽象方法只能定义在抽象类中 子类必须对起抽象方法重写
abstract sayHello(): void;
}
class Dog extends Animal {
sayHello() {
// 在类的方法中 super表示当前类的父类
//super.sayHello();
console.log('汪汪汪');
}
}
class Cat extends Animal {
} // 报错 没有实现s对ayHello重写
const dog = new Dog('小黑');
dog.sayHello();
console.log(dog);
//const ani = new Animal(); // 报错 无法创建实例
})();
泛型
- 在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的特性
// function fn(a: number): number {
// return a;
// }
/**
* 在定义类或函数时 如果遇到类型不明确就可以使用泛型
*
*/
function fn<T>(a: T): T {
return a;
}
// 直接调用具有泛型的函数
const result = fn(123); // 不指定泛型 ts会自动对类型进行推断
const result2 = fn<string>('hello'); // 指定泛型
// 多个
function fn2<T, K>(a: T, b: K): T {
return a;
}
const result3 = fn2<number, string>(123, 'hello');
interface Inter {
length: number
}
function fn3<T extends Inter>(a: T): number {
return a.length;
}
fn3('122'); // 3
//fn3(123); // 类型“number”的参数不能赋给类型“Inter”的参数
fn3({length: 10}); // 10
// 定义类也可以使用泛型
class MyClass<T> {
name: string;
constructor(name: string) {
this.name = name;
}
}
const c = new MyClass<string>('哈哈哈');
//const d = new MyClass<number>(123); // 类型“number”的参数不能赋给类型“string”的参数
属性的封装
- public 公有修饰符,可以在实例外使用修饰符的属性或行为。
- protected 受保护修饰符,可以在类(子类)内使用修饰符的属性或行为
- private 私有修手符,只可以在当前类(非子类)使用修饰符的属性或行为。
- readonly 将属性设置为只读的,只读的属性不可被修改,只读属性必须在声明时或构造函数里被初始化。
(function() {
// 定义一个人的类
class Person {
// ts可以在属性前添加修饰符
/**
* public 修饰的属性可以在任意位置访问(修改)默认值
* private 私有属性 只能在对象内部中访问(修改)默认值
* protected 受保护的属性 只能在当前类和当前类的子类访问
*
*/
private _name: string;
age: number;
constructor(name: string, age: number) {
this._name = name;
this.age = age;
}
// 定义方法 获取name属性
// getName() {
// return this._name;
// }
// 定义方法 设置name属性
// setName(value: string) {
// this._name = value;
// }
// ts中设置getter方法的方式
get name() {
console.log('get name() 方法执行了---');
return this._name;
}
set name(value: string) {
this._name = value;
}
}
const per = new Person('猴子', 18);
/**
* 现在属性是在对象中设置的 属性可以任意被修改
* 属性被任意修改会导致对象中的数据变得非常不安全
*
*/
//per._age = 20; // 报错 不能访问
//per.name = '八戒';
//console.log(per); // 输出: {name: "八戒", age: 20}
// per.setName('八戒');
// console.log(per.getName()); // 输出: 八戒
console.log(per.name); // get name() 方法执行了--- 猴子
per.name = '八戒';
console.log(per.name); // 八戒
class A {
protected num: number;
constructor(num: number) {
this.num = num;
}
}
class B extends A {
test() {
console.log(this.num);
}
}
const b = new B(123);
// b.num = 55; // 只能在类“A”及其子类中访问
class C {
// 可以直接将属性定义在构造函数中
constructor(public name: string, public age: number) {
this.name = name;
this.age = age;
}
}
const c = new C('xxx', 123);
console.log(c); // {name: "xxx", age: 123}
})();