文章目录
前言
有一位著名大佬说过:所有javascript的代码今后都可以typescript代替。这句话是绝对正确的,因为typescript是javascript的超集。相对javascript最大的特点就是多了类型检测等功能
基本数据类型
string
类型限定的表示形式就是在定义的变量名后面加上冒号,在加上需要限定的类型,如下
let name: string = "bob";
name = "smith";
let name: string = `Gene`;
let age: number = 37;
let sentence: string = `Hello, my name is ${ name }.
I'll be ${ age + 1 } years old next month.`;
Boolean
除了多了个类型限定,其余基本上和js一样
let isDone: boolean = false;
number
和JavaScript一样,TypeScript里的所有数字都是浮点数。 这些浮点数的类型是 number。 除了支持十进制和十六进制字面量,TypeScript还支持ECMAScript 2015中引入的二进制和八进制字面量。
let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
let binaryLiteral: number = 0b1010;
let octalLiteral: number = 0o744;
数组-创建数组的三种方法
let arr1:number[] = [1,2,3,5]
下面用到了泛型,后面有讲到泛型,先解释一下:泛型就是定义时还不确定到底是什么样的类型,到用的时候才会确定类型
let arr2:Array<string> = ['str','adas']
let arr3:any[] = [12,454,'sad',true]
元组 Tuple
元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同
let arr:[string,number,boolean] = ["ts",18,false]
console.log(arr);
枚举类型 enum
默认情况下,从0开始为元素编号。 你也可以手动的指定成员的数值。
enum Flag {success=1,error=-1}
let f:Flag = Flag.error //f = -1
enum Color {
red,
blue,
orange
}
let c:Color = Color.blue
console.log(c); //2
enum Color2 {
red,
blue=5,
orange
}
console.log(Color2.orange); //6
任意类型 any
any类型你可以简单理解为,以前的javascript创建变量的类型,在编程阶段还不清楚类型的变量指定一个类型
let num:any = 123
num = 'str';
console.log(num);
任意类型的一个小用处
var oBox:any = document.querySelector('obox')
oBox.style.color = 'red'
null和undefined
null 和 undefined 其他数据类型(never)的子类型
let u: undefined = undefined;
let n: null = null;
never
never类型:是其他类型(包括null和undefined)的子类型,代表从不会出现的值,这意味着声明never变量
var n:never
// a = 123 报错
n = (()=>{
throw new Error('错误')
})()
Object
object表示非原始类型,也就是除number,string,boolean,symbol,null或undefined之外的类型。
declare function create(o: object | null): void;
create({ prop: 0 }); // OK
create(null); // OK
create(42); // Error
create("string"); // Error
create(false); // Error
create(undefined); // Error
void
void类型:typescript中的void表示没有任何类型,一般用于定义方法是没有返回值
function run():void{
console.log(123);
}
console.log(run());
function hasReturn():number{
return 123
}
联合类型
就是一个变量可以存在多个类型可以用,‘|’ 此符号链接这些类型
let x:number | boolean | undefined
类型断言
这东西 很有用
有时候你会遇到这样的情况,你会比TypeScript更了解某个值的详细信息。 通常这会发生在你清楚地知道一个实体具有比它现有类型更确切的类型。
通过类型断言这种方式可以告诉编译器,“相信我,我知道自己在干什么”。 类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。 它没有运行时的影响,只是在编译阶段起作用。 TypeScript会假设你,程序员,已经进行了必须的检查。
类型断言有两种形式。 其一是“尖括号”语法
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
as语法
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
typescript的函数
typescript的定义函数方式基本本上相对于javascript就多一个类型限定就可以了
function run1():string{
return 'tun'
}
匿名函数法
let run2 = function():string{
return 'run2'
}
如果函数有两个返回值
函数的传参
function getInfo(name:string,age:number):string{
return `${name}+${age}`
}
let getInfo2=function(name:string,age:number):string{
return `${name}+${age}`
}
function getInfo3():void{
}
函数的类型具有相同的两个部分:参数的类型和返回类型。写出整个函数类型时,两个部分都是必需的。我们像参数列表一样写出参数类型,
为每个参数指定名称和类型。该名称只是为了提高可读性。相反,我们可以这样写:
let myAdd2: (baseValue: number, increment: number) => number = function (
x: number,
y: number
): number {
return x + y;
};
可选参数
es5里面的方法的实参和形参不一样,但是ts中的必须一样,如果不一样就需要配置可选参数,加个问号 就可选了 可传可不传
可选参数必须配置到参数的最后面 例如下面如果这样写 就是错的 age?:number,name:string
function getSelect(name:string,age?:number):string{
if(age){
return `${name}+${age}`
}else{
return `${name}+Don.t want to say age`
}
}
默认参数
es6和ts都可以设置默认参数
function getSelect2(name:string,age:number=20):string{
if(age){
return `${name}+${age}`
}else{
return `${name}+Don.t want to say age`
}
}
剩余参数
用es6的剩余运算符就可以了
function sum(a:number,b:number,c:number,d:number):number{
return a+b+c+d
}
function sum2(a:number,...result:number[]):number{
let sum = 0
result.forEach(e=>{
sum=sum+e
})
return sum+a
}
函数的重载
java 中的重载是指两个或者两个以上的同名函数,但他们的参数不一样,这是会出现函数的重载
typescript中的重载,通过为同一个函数提供多个函数类型定义来试一下多种功能的目的
ts为了兼容es5 以及 es6 冲下的写法和java中有区别
es5中出现的同名方法,下面的方法会替换上面的方法
function getTs(name:string):string;
function getTs(age:number):string;
function getTs(str:any):any{
if(typeof str === 'string'){
return '我叫'+str
}else{
return `我的年龄是:${str}`
}
}
console.log(getTs('xiaoMing'));
typescript的类
类定义的属性和方法加上类型限定
class Person{
name:string //前面省略了public属性
constructor(n:string){
// 构造函数 实例化类的时候触发的方法
this.name = n
}
run():void{
console.log(this.name+' is running');
}
getName():string{
return this.name
}
setName(name:string):void{
this.name = name
}
}
const p = new Person('李四')
p.run()
alert(p.getName())
alert(p.setName('琪琪'))
类里面的三类修饰符
- public :共有 在类里面 子类 类外面都可以方法
- protected:保护了类型 在类里面,子类里面可以访问,在类外部没法访问
- provate: 私有 在类里面可以访问, 其他地方都不可以
如果属性不加修饰符 就是public 修饰的
class Person{
private name:string //属性“name”为私有属性,只能在类“Person”中访问。
constructor(name:string){
this.name = name
}
run():void{
console.log(`${this.name} 在运动`);
}
}
如何实现类的继承
先聊聊js的三种继承方式
- 对象冒充继承:可以构造函数上的属性的和方法,无法实现原型链上的方法的继承
- 原型链上的继承:既可以继承原型连上的属性和方法,也可以继承构造函数上面的属性和方法,但是实例化的子类不能给父类传参
- 原型链加构造函数的组合继承模式:具备以上两者的所有优点
1. 对象冒充继承
//es5里面的类(构造函数),定义属性和方法
function Person() {
this.name = "zhangs"
this.age = 20
this.run = function () {
console.log(this.name + 'sports');
}
}
// 原型链上扩展属性和方法,会被多个实例共享
Person.prototype.sex = 'man'
Person.prototype.work = function(){
console.log(this.name + 'is working ');
}
var p =new Person()
p.work()
// 类里面的静态方法
Person.eat = function () {
console.log('eat rice');
}
调用静态方法
Person.eat()
//ES5继承 web 继承 Person
对象冒充实现继承,无法实现原型连上的方法继承
function Web(){
Person.call(this) //对象冒充实现继承,无法实现原型连上的方法继承
}
var w = new Web()
w.run()
w.work() //报错
** 2. 原型链上的继承**
//原型链实现继承
// 既可以继承原型连上的属性和方法,也可以继承构造函数上面的属性和方法
function Web(){
}
Web.prototype = new Person(); //Person时候是上面定义的父类
var w = new Web()
w.run()
w.work()
原型链实现继承的问题:实例化子类的时候不能给父类传参
function Web() {
}
Web.prototype = new Person();
var w = new Web()
w.run()
3.原型链加构造函数的组合继承模式
function Web(name,age) {
Person.call(this,name,age)
}
Web.prototype = Person.prototype;
var w = new Web('wangwu',18)
w.run()
ts的继承
// ts 如何实现继承 extends,super
class Person{
name:string
constructor(name:string){
this.name = name
}
run():void{
console.log(`${this.name} 在运动`);
}
}
class Web extends Person{
constructor(name:string){
super(name) //初始化父类构造函数
}
}
var w = new Web('李四')
w.run()
类中定义静态方法和属性
class Person{
name:string
static attr:string = 'everyone';
constructor(name:string){
this.name = name
}
run():void{
console.log(`${this.name} 在运动`);
}
// 静态方法 static关键字 没法直接调用类里面的非静态属性
static sayHellow(){
console.log('Hello'+this.attr);
}
}
Person.sayHellow()
ts 中的多态
ts 中的多态:父类定义一个方法不去实现,让继承它的子类去实现 每一个子类都有不同的表现
class Animal {
specis:string
constructor(specis:string){
this.specis = specis
}
eat(){
}
}
class Dog extends Animal{
constructor(specis:string){
super(specis)
}
eat(){
console.log(`${this.specis} 吃骨头`);
}
}
class cat extends Animal{
constructor(specis:string){
super(specis)
}
eat(){
console.log(`${this.specis} 吃老鼠`);
}
}
typescript中抽象类
用abstract 关键字定义的抽象类和抽象方法 抽象类中的抽象方法
不包含具体实现并且必须在派生类中实现,和java差不多
注意:abstract抽象方法智能是放在抽象类里面
abstract class Animal {
specis:string
constructor(specis:string){
this.specis = specis
}
abstract eat():any
}
// var ani = new Animal() 报错
class Dog extends Animal{
constructor(specis:string){
super(specis)
}
// 抽象类的子类必须实现抽象类里面的抽象方法
eat(){
console.log(`${this.specis} 吃骨头`);
}
}
class cat extends Animal{
constructor(specis:string){
super(specis)
}
// 抽象类的子类必须实现抽象类里面的抽象方法
eat(){
console.log(`${this.specis} 吃老鼠`);
}
}
typescript中的泛型
泛型就是定义的时候还不知道,不确定这个变量是什么类型,到用的时候才确定她的类型
泛型可以用来创建可重用的组件,一个组件可以支持多重昂类型的数据
这样用户就可以以自己的数据类型来使用组件
泛型可以使其支持多种类型 并且传入什么返回什么 具体是什么类型是调用这个方法时决定的
function getData3<T>(value:T):T{
return value
}
getData3<number>(123)
泛型和any类型的区别
如果有一个函数的参数是any类型,返回一个any类型,等于放弃了类型检查,传入和返回的类型可以不同
function getData1(value:any):any{
return value //放弃了类型检查,传入可以和返回的不同
}
泛型类
泛型类 :比如有个求最小值的算法,需要同时支持放回数字和字符串两种类型
class MinClass<T>{
public list:T[] = [];
add(...num:T[]):void{
this.list = [...num]
}
min():T{
var minNum = this.list[0]
for(let i=0;i<this.list.length;i++){
if(minNum > this.list[i]){
minNum = this.list[i]
}
}
return minNum;
}
}
var m = new MinClass<number>()
var s1 = new MinClass<string>()
m.add(2,3,4)
console.log(m.min());
s1.add('who','are','you')
console.log(typeof m.min());
typescript的接口
- 面向对象编程中接口是一种贵方发定义,它定义了行为和动作的规范,
- 在程序设计里面,接口起到一定的限制和规范作用,接口定义了一批类
- 所需要的遵守的规则,接口不关心这些类的内部状态数据,也不关心这些类里面方法的实现细节,它值规定了这批类里面必须提供某些方法,提供这些方法的类就可以满足
- 实际的需要,typescript中的接口类似于java,同时还增加了更灵活的接口类型,包括属性函数,可索引和类等
属性接口
interface FullName{
firstName:string
secondName:string
}
function printName(name:FullName){
// 必须传入对象 firstName
console.log(name.firstName+name.secondName);
}
传入的参数必须有firstName,secondName,可以传入多余的属性,但是多余的属性使用时
还是会报错
var obj = {
age:20,
firstName:'zhang',
secondName:'san'
}
printName(obj)
printName({ //传入的参数必须是firstName,secondName,这种方法多了属性会报错
age:20,
firstName:'zhang',
secondName:'san'
})
可选属性,在属性后面加个问号即可
interface FullName{
firstName:string
secondName?:string
}
function getName(name:FullName){
console.log(name);
}
getName({firstName:'zhang'})
实践 ts封装ajax
interface Config{
url:string
type:string
data?:string
dataType:string
}
function ajax(config:Config){
const xhr = new XMLHttpRequest()
xhr.open(config.type,config.url,true)
xhr.send(config.data)
xhr.onreadystatechange = function(){
if(xhr.readyState ==4 && xhr.status === 200){
console.log('success');
if(config.dataType === 'json'){
console.log(JSON.parse(xhr.responseText))
}else{
console.log(xhr.responseText);
}
}
}
}
ajax({
type:'get',
url:'http://a.itying.com/api/productlist',
dataType:'json'
})
函数接口
函数类型接口:对方法传入的参数,以及返回值约束
// 加密的函数类型接口
interface encrypt{
(key:string,value:string):string;
}
const md5:encrypt = function(key:string,value:string):string{
return key+value;
}
md5('name','sattre')
const des:encrypt = function(key:string,value:string):string{
return key+value+'des'
}
还可以结合泛型
// 第一种
interface ConfigFn{
<T>(value:T):T;
}
var setData:ConfigFn = function<T>(value:T):T{
return value
}
setData<string>('hello')
// 第二种
interface configFn<T>{
(value:T):T
}
function setData<T>(value:T):T{
return value
}
var mySetData:configFn<string> = setData
mySetData('24')
可索引接口
可索引接口,数组,对象的约束
const array:string[] = ['sds','sdadas']
const array1:Array<string> = ['sds','sdadas']
//定义了数组的索引必须是number类型,值必须是string类型
interface UseArr{
[index:number]:string
}
const array3:UseArr = ['string','sadasd']
//定义了对象的索引必须是number类型,值必须是string类型
interface UseOBj{
[index:number]:string
}
const obj:UseOBj = {1:'hello',2:'everyone'}
类接口
类类型接口:对类的约束 和抽象类有点相似
注意:这里的关键字时implements
interface Work{
name:string
run(type:string):void
}
class Coder implements Work{
name:string
constructor(name:string){
this.name = name
}
run(type:string){
console.log(this.name + ' run '+type);
}
}
class Hr implements Work{
name:string
constructor(name:string){
this.name = name
}
run(type:string){
console.log(this.name +' run '+type);
}
}
class Hr implements Work{
name:string
constructor(name:string){
this.name = name
}
run(type:string){
console.log(this.name +' run '+type);
}
}
const zhangsan = new Coder('zhansan')
zhangsan.run('code')
const lisi = new Hr('lisi')
lisi.run('project')
接口的继承
接口的继承和类的继承基本上差不多
interface Drink{
color():void;
}
interface Sodas extends Drink{
other():void;
}
class coke implements Sodas{
constructor(){
}
other(){
}
color(){
}
}