2

typescript类型

1、函数多参

type addType = (x: number, y: number) => number
let addxy: addType = (ar1, ar2) => ar1 + ar2;

// 可选参数
type addType2 = (x: number, y: number, z?: number) => number
let addxyz: addType2;
addxyz = (x, y) => x + y;
addxyz = (x, y, z) => x + y + z;  // 这种函数会覆盖前面的

let addx1 = (x: number, y = 3) => {
    return x + y
}
addx1(1);
addx1(2, 2);

// 多个参数
let addx2 = (ar1: number, ...args: number[]) => {}

2、函数重载

function reverse(x: number): number;
function reverse(x: string): string;

// 函数实体
function reverse(x: any) { 
    if (typeof x === 'number') {
        return Number(x.toString().split('').reverse().join(''));
    } else if (typeof x === 'string') {
        return x.split('').reverse().join('');
    }
}

reverse(1)
reverse('abc')
reverse(true) // error 只能传number string

3、泛型

  • 问题:
const getArray = (value: any, times: number = 5) => {
    return new Array(times).fill(value)
}
console.log(getArray(5, 4).map(item => item.length))  // 因为 value是any,但是lenth只有value是字符串的时候才可用, 但是这里没有报错
  • 方案:
const getArray2 = <T>(value: T, times: number = 5): T[] => {
    return new Array(times).fill(value)
}
console.log(getArray2('abc', 5).map(item => item.length)) // ok
console.log(getArray2(12345, 5).map(item => item.length)) // error
// 假如需要value是length属性的
interface IwithLength {
    length: number
}

const getArray22 = <T extends IwithLength>(value: T, times: number = 5): T[] => {
    return new Array(times).fill(value)
}
getArray22(12345, 5);// error
getArray22('12345', 5);// ok
// 多个泛型
const getArray3 = <T, U>(x: T, y: U, times = 5): Array<[T, U]> => {
    return new Array(times).fill([x, y])
}
console.log(getArray3(1, 2))
console.log(getArray3('a', 2))
// 与keyof结合
const getProps = <T, K extends keyof T>(obj: T, prop: K) => {
    return obj[prop]
}
var myObj = {
    name: 'xing',
    age: 32
}
console.log(getProps(myObj, 'name'))
console.log(getProps(myObj, 'year')) // error
  • 泛型类型
type F1 = <T, U>(x: T, y: U, times: number) => Array<[T, U]>

let getArray4: <T, U>(x: T, y: U, times: number) => Array<[T, U]>

interface F2 {
    <T, U>(x: T, y: U, times: number): Array<[T, U]>
}

interface F3<T, U> {
    (x: T, y: U, times: number): Array<[T, U]>
    array: [T, U]
}

function xxx<T, U>(x: T, y: U, times: number): Array<[T, U]> {
    return [[x, y]]
}

4、类

4.1 private static public protected

测试案例

/**
 * readonly 只读属性
 * static 类本身的属性,而不是类的实例
 * public 任何地方都能访问
 * private 只能在自己的类中使用(不包含实例)
 * protected 只能在自己的类和子类中使用(不包含实例)
 */
class Parent {
    public readonly x: number;
    public x1: number;
    private x2: number;
    protected x3: number;
    static x4: number;

    constructor() {
        this.x = 1;
        this.x1 = 1;
        this.x2 = 2;
        this.x3 = 2;
        this.x4 = 2;  //error static属性 this指向是Parent函数,而不是parent的实例
        Parent.x4 = 8; // ok
    }
    public sayP1() { }
    private sayP2() { }
    protected sayP3() { }
    static sayP4() { }
}

class Son extends Parent {
    z = 1;
    constructor() {
        super();
        console.log(super.x1)
        console.log(super.x2) // error 私有属性 只有
        super.sayP2() // error 私有属性 只有
        console.log(super.x3)
        super.sayP3()
        console.log(super.x4) //error
    }
}

const par = new Parent();
console.log(par.x1)
console.log(par.x2) // error
console.log(par.x3) // error
par.sayP1()
par.sayP2() // error
par.sayP3() // error

const son = new Son();
console.log(son.x1)
console.log(son.x2) // error
console.log(son.x3) // error
son.sayP1()
son.sayP2() // error
son.sayP3() // error

4.2 可选属性

class Info {
    name = 'haixing';
    age?: number;
    constructor(x: number, y?: string) {

    }
}
const info1 = new Info(1);
console.log(info1.name)
console.log(info1.age)
const info2 = new Info(1, 'la');

4.3 get & set

class OperString {
    private _name: string = 'haixing'
    get oString() {
        return this._name
    }
    set oString(newValue: string) {
        this._name = newValue;
    }
}

const o1 = new OperString();
console.log(o1.oString)
o1.oString = 'ggg'

4.4 抽象类和抽象方法

abstract class People { // 抽象类不能用于实例创建,只能继承
    public abstract getPerson(): void; // 抽象方法不用实现 只是为子类中提供类型
}

// const peo = new People(); // error
class SonPeople extends People {
    getPerson() {
        // 必须有这个方法,因为父类中已经定义了此方法的抽象方法
    }
}

const sonp = new SonPeople();
sonp.getPerson();

4.4 接口和类

// 用接口修饰类
interface Good {
    type: string
}
class MyGood implements Good {
    type = 'aaa';
    hehe = 'good'
}

5、通过索引访问类型

interface IPE {
    age: number
    name: string
}
type myAge = IPE['age'] // number
// type myAge2 = IPE.age; // error

function getProperty<T, K extends keyof T>(o: T, p: K): T[K] {
    return o[p]
}

interface Objs<T> {
    [key: string]: T
}
let key: keyof Objs<number>  // 类型是 string | number
const objsT: Objs<number> = {
    name: 18
}
let keys: Objs<number>['name']  // 类型是 number

6、ES6模块化

// 模块化
export useState
export useEffect
export default react

import react ,{useState,useEffect} from 'react'

7、命名空间

// space.ts
namespace Validation {
    const year = 2006;
    export const name = 'lihaixing';
    export const age = 32;
}

// 引入 多个命名空间会合并  
// 查找 ts => tsx => .d.ts => package.json type属性
<reference path="./space.ts" />
console.log(Validation.name)

// 用import也可以
import MyName = Validation.name

// 如果引用全局库 types
<reference types="react" />
// 模块库
import React from 'react'

8、声明文件合并

interface AA {
    name: string
    getRes(input: number): number
}
interface AA {
    // name:number; // error 冲突了
    age: number
    getRes(input: string): string // 如果是函数会重载
}
// 声明合并了,如果相同属性,会覆盖
let me: AA = {
    name: 'haix',
    age: 12,
    getRes: (input: any): any => {
        if (typeof input === 'string') {
            return 'a'
        } else {
            return 1
        }
    }
};

9、声明全局属性和全局模块

  • 全局属性
// d.ts声明文件,如果是全局属性,要用declare 来修饰
declare function FnForget(): string;
declare let hulala: string;
function getTitle() {
    return 'good'
}
  • 全局模块

文档

// module-plugin.d.ts

/*~ On this line, import the module which this module adds to */
import * as m from 'someModule';
/*~ You can also import other modules if needed */
import * as other from 'anotherModule';
declare module 'someModule' {
    /*~ Inside, add new function, classes, or variables. You can use
     *~ unexported types from the original module if needed. */
    export function theNewMethod(x: m.foo): other.bar;

    /*~ You can also add new properties to existing interfaces from
     *~ the original module by writing interface augmentations */
    export interface SomeModuleOptions {
        someModuleSetting?: string;
    }

    /*~ New types can also be declared and will appear as if they
     *~ are in the original module */
    export interface MyModulePluginOptions {
        size: number;
    }
}
// 没有声明文件的库
declare module 'react-native'

lihaixing
463 声望719 粉丝

前端就爱瞎折腾