02|typescript常用实例

2020-05-17  本文已影响0人  雪燃归来

一、定义索引数组

interface StringArray{
    [index: number]: string
}
let chars: StringArray = ['A', 'B']

interface Names{
    [x:string]: string,
    [y:number]: string
}

二、定义函数

//example one
function add(x:number, y:number){
  return x + y
}
//example two
 let add:(x:number, y:number) => number

//example three
interface add{
    (x:number, y:number): number
}
//example four
type Add = (x:number, y:number) => number

//实现具体的函数
let add:Add = (a,b) => a + b

// 定义混合类型
interface Lib{
    (): void;                        //表明Lib类是一个不带返回值得函数
    version: string;            //表明Lib类有version这个属性
    dosomething():void    // 表明Lib类有dosomething这个方法
}

function getLib(){
    let lib:Lib = (() => {}) as Lib;
    lib.version = '1.0.1';
    lib.dosomething = () => {}
    return lib;
}

let lib1 = getLib()
lib1()
lib1.dosomething()

函数参数可选

function add5(x:number,y?:number){
    return y ? x + y : x;
}

函数参数默认值

function add6(x:number, y=0, z:number,q=1){
    return x + y + z + q
}
console.log(add6(1, undefined, 3))

函数参数的剩余变量

function add7(x:number, ...rest:number[]){
    return x + rest.reduce((pre, cur) => pre + cur)
}
console.log(add7(1,2,3,4,5))

函数的重载

// 函数的重载
function add8(...rest:number[]):number;
function add8(...rest:string[]):string;
function add8(...rest:any[]):any{
    let first = rest[0];
    if(typeof first === 'string'){
        return rest.join('')
    }
    if(typeof first === 'number'){
        return rest.reduce((pre, cur) => pre + cur)
    }
}

console.log(add8(1,2,3))
console.log(add8('a','b','c'))

三、ts中的类

类的定义

class Dog {
    constructor(name:string){
        this.name = name
    }
    name: string
    run(){}
}
console.log(Dog.prototype)              //{run: ƒ, constructor: ƒ}
let dog =new Dog('wangwang')
console.log(dog)                              // Dog {name: "wangwang"}

\color{red}{注意:name属性存在实例上,而不是类上面。}
类的继承

class Husky extends Dog{
    constructor(name:string, color:string){
        super(name);
        this.color = color;
    }
    color:string
}

类的修饰符
1、public 默认设置
2、protected: 只能在类自身和子类中使用(也就是只能继承)
3、private:只能在类本身使用
4、readonly: 只读属性
5、static:静态修饰符(只能通过类名来调用,也可以被继承)
6、构造函数的参数用修饰符修饰后,会转化成示例属性

class Husky extends Dog{
    constructor(name:string, public color:string){
        super(name);
        this.color = color
    }
    // color:string
}

let husky = new Husky('wangwang','white')
console.log(husky)

抽象类
抽象类只能被继承,不能被实例化
抽象方法的好处是,明确知道子类中有具体的实现,所以就不在父类中实现了
抽象类的好处就是能抽出事务共性,有利于代码的复用和扩展

abstract class Animal{
    eat(){
        console.log('eat')
    }
   abstract sleep():void
}
//let animal = new Animal()  //Cannot create an instance of an abstract class.ts(2511)
class Dog extends Animal{
    constructor(){
        super();
    }
    sleep(){
        console.log('sleep...')
    }
}

let dog = new Dog()
dog.eat()

抽象类实现多态

abstract class Animal{
    eat(){
        console.log('eat')
    }
    abstract sleep():void
}
//let animal = new Animal()  //Cannot create an instance of an abstract class.ts(2511)
class Dog extends Animal{
    constructor(){
        super();
    }
    sleep(){
        console.log('Dog sleep...')
    }
}

class Cat extends Animal{
    sleep(){
        console.log('Cat sleep...')
    }
}

let dog = new Dog()
let cat = new Cat()
let animals: Animal[] = [dog, cat]
animals.forEach(i => {
    i.sleep()
})
image.png

通过返回this实现链式调用

class WorkFlow{
    step1(){
        return this;
    }
    step2(){
        return this;
    }
}

new WorkFlow().step1().step2()

继承的时候 this也可以表现出多态,既可以是父类型,也可以使子类型

class WorkFlow{
    step1(){
        return this;
    }
    step2(){
        return this;
    }
}

class MyFlow extends WorkFlow{
    next(){
        return this;
    }
}

new MyFlow().next().step1().next().step2()

四、ts中接口与类的关系

一个接口可以约束一个类成员有哪些属性以及他们的类型
类实现接口时,必须要实现接口所有的属性和方法
接口只能约束类的公用成员
接口不能约束类的构造函数

interface Human{
    name: string;
    eat():void;
}

class Asian implements Human{
    constructor(public name: string){
        this.name = name
    }
    eat(){}
    sleep(){}
}

接口也可以继承接口
一个接口可以继承多个接口
可以抽离处可重用的接口,也可以将多个接口合并成一个接口

interface Human{
    name: string;
    eat():void;
}

class Asian implements Human{
    constructor(public name: string){
        this.name = name
    }
    eat(){}
    sleep(){}
}
interface Man extends Human{
    run(): void
} 
interface Child{
    cry():void
}

interface Boy extends Man,Child{}
let boy:Boy = {
    name: '',
    run(){},
    eat(){},
    cry(){}
}

接口可以继承类,接口将类的成员抽象了出来,只有类的成员结构,没有具体的实现

class Auto {
    state = 1
}
interface AutoInterface extends Auto{

}

class C implements AutoInterface{
    state = 1
}

class Bus extends Auto implements AutoInterface{

}
let c = new C();
console.log(c.state)
image.png

五、ts中的泛型

可以自定义化函数参数的类型
使用泛型定义一个函数

function log<T>(value: T): T{
    console.log(value)
    return value
}

log<string[]>(['a', 'b'])
log(['a','b'])

使用泛型定义一个函数类

function log<T>(value: T): T{
    console.log(value)
    return value
}

log<string[]>(['a', 'b'])
log(['a','b'])

type Log = <T>(value: T) => T
let myLog:Log = log

使用泛型定义接口

interface Log{
    <T>(value: T): T
}
function log<T>(value: T):T{
    console.log(value)
    return value
}
interface Log<T = string>{
    (value: T): T
}
// let myLog: Log<number> = log
let myLog: Log = log;

泛型不能约束类的静态成员

class Log<T>{
    // Static members cannot reference class type parameters.ts(2302)
    static run(value: T){ 
        console.log(value)
        return value
    }
}
interface Length{
    length: number
}

function log<T extends Length>(value: T): T{
    console.log(value, value.length)
    return value
}
log([1])
log('123')
log({length: 1})

泛型的好处
1、函数和类可以轻松地支持多种类型,增强程序的扩展性
2、不必写多条函数重载,很长的联合类型声明,增强代码可读性
3、灵活控制类间的约束

六、类型兼容性

(一)、接口的兼容性

X 兼容 Y: X(目标类型) = Y(源类型)

interface X{
    a: any;
    b: any;
}

interface Y {
    a: any;
    b: any;
    c: any;
}
let x: X = {a: 1, b: 1}
let y: Y = {a:1, b:2, c:3}
x = y
// y = x  // Y 不兼容 X

(二)、函数的兼容性

1)参数的个数

参数少的 兼容参数多的

// 函数的兼容性
type Handler = (a:number) => void;
function hof(handler: Handler){
    return handler;
}

// 1)参数的个数
let handler1 = (a:number) => {}
hof(handler1)
let handler2 = (a:number,b:number) => {}
hof(handler2)  ////Argument of type '(a: number, b: number) => void' is not assignable to parameter of type 'Handler'.ts(2345)

/**固定参数可以兼容可选参数和剩余参数**/
/**可选参数是不兼容固定参数和剩余参数的**/
/**剩余参数是可以兼容可选参数和固定参数的**/
let a = (p1:number, p2:number) => {} 
let b = (p1?:number, p2?:number) => {}
let c = (...args:number[]) => {}

// ok
a = b;
a = c;
// unassignable
b = a;
b = c;
// ok
c = a
c = b
2)参数的类型

类型多的兼容类型少的

interface Point3D{
    x: number
    y: number
    z: number
}

interface Point2D{
    x: number
    y: number
}

let p3d = (point: Point3D) => {}
let p2d = (point: Point2D) => {}

// ok
p3d = p2d
// assignable
p2d = p3d
3)参数的返回值类型

返回值多的兼容返回值多少的(鸭式变形法)

let p3d = (point: Point3D) => {}
let p2d = (point: Point2D) => {}

let f = () => ({name: 'Alice'})
let g = () => ({name: 'Alice', location:'beijing'})
// ok
f = g
// unassignable
g = f

function overload(a:number, b:number): number;
function overload(a:string, b:string): string;
function overload(a: any, b:any): any {}

(三)、枚举的兼容性

枚举类型和数字是可以相互兼容的

enum Fruit { Apple, Banana }
enum Color { Green, Red }

let fruit: Fruit.Apple = 3
let no:number = Fruit.Apple

枚举类型是不相互兼容的

let color: Color = Fruit.Apple  // Type 'Fruit.Apple' is not assignable to type 'Color'.ts(2322)

(四)、类的兼容性

类之间只要有相同的实例属性和方法,就可以兼容,静态/构造属性、方法不参与兼容性比较

class A {
    constructor(p:number, q:number){}
    id: number = 1
}
class B {
    static s = 1;
    constructor(p: number){}
    id: number = 1
}

let aa = new A(1,2)
let bb = new B(2)
// ok
aa = bb
// ok
bb = aa

当类中存在private私有变量时,只有子类和父类兼容

class A {
    constructor(p:number, q:number){}
    id: number = 1
    private name = 'antiai'
}

class C extends A{}

let aa = new A(1,2)
let cc = new C(1,2)
aa = cc
cc = aa

(四)、泛型的兼容性

只有类型参数T被泛型接口使用的时候,才会影响泛型的兼容性

// 兼容
interface Empty<T>{

}

let obj1: Empty<number> = {}
let obj2: Empty<string> = {}

obj1 = obj2
obj2 = obj1
// 不兼容
interface Empty<T>{
    value: T
}

let obj1: Empty<number> = {}
let obj2: Empty<string> = {}

obj1 = obj2
obj2 = obj1

(五)、泛型函数的兼容性

如果两个泛型参数的定义相同,但是没有指定类型参数,他们之间也是相互兼容的

let log1 = <T>(x: T) => {
    console.log(x)
    return x
}
let log2 = <U>(y: U) => {
    console.log(y)
    return y
}

log1 = log2
log2 = log1

结构之间兼容:成员少的兼容成员多的
函数之间兼容:参数多的兼容参数少的

上一篇下一篇

猜你喜欢

热点阅读