ts基础知识-(持续更新)

113 阅读7分钟

ts中文官网:https://www.tslang.cn/docs/handbook/jsx.html

安装 运行编译

tsc -v // 没有就安装 Version 4.7.3
sudo npm install typescript -g // mac环境
tsc test.ts// 编译成js给浏览器识别
tsc init // 项目中 创建tsconfig.js

基于js 范围的话 ts > es6 > es5 > js

组合类型

类型断言:“尖括号”语法和as语法
如:
let someValue: any = "777";
let strLength: number = (<string>someValue).length;
let strLength: number = (someValue as string).length;

// 定义组合数组的两种方式
let numStrArr: (number | string)[] = [1, 2, 'a', 'b']
let boolStrArr: Array<boolean | string> = [true, true, 'a']
但是上面这个写着好累,所以用元祖比较好,在需要多个类型的情况
// 数组合并了相同类型的对象,而元组(Tuple)合并了不同类型的对象。就不需要用组合类型了

// 定义一对值分别为string和number类型的元组 Tuple
let tuples: [string, number]
tuples = ['name', 20] // 其他就会报错 顺序必须一致,数组顺序可以不一致
tuples[3] = 'world' // 不能将类型“"world"”分配给类型“undefined”。v4版本
// v3版本 当访问一个越界元素,会使用联合类型替代,字符串可以赋值给(string | number)类型,但是不能赋予布尔值或者其他

枚举类型 enum

// const方式定义变量,只是限制了变量的引用不可变,但是对象的属性值仍然是可以改变的
// readonly ReadonlyArray 是修饰属性的
// 枚举 申明固定不变的对象
// 通过下标的方式来取值或者通过值反向取到下标 数字美剧
enum Color { Red = 1, Green, Blue } // 默认情况下,从0开始为元素编号。也可以自己设置比如1
let c: Color = Color.Blue

// 字符串枚举 得到下标 c['Red']
enum Color { Red = 'Red', Green = 'Green', Blue = 'Blue' }


别名在JSX中不能写成:xxx 得写成as xxx


 还有Unknown,any,never,viod,in,infer, keyof等,当然几乎js有的ts也有

函数 function

// 如下:参数虽然不固定,但是每个都必须为number类型,返回值也是number
function sum2(...arg: number[]): number {
    return arg.reduce(function(sum, val) {
        return sum + val
    }, 0)
}
// ?: 可选参数函数
// 如下:如果传一个参数获取值,传两个参数就是设置值 
let obj = {}
function fn(key: string, val?: any): any {
    if(val) {
        obj[key] = val
    } else {
        return obj[key]
    }
}

类 class 继承 extends

abstract 抽象类关键字 子类必须定义方法
// 对象在ts中不可动态添加属性
// class也不可动态添加属性,必须要定义好实例属性,才能赋值
// 函数定义形参类型,用来约束调用,私有属性只在此类可以访问
class Animal {
    private static color: string = 'red'// 私有静态属性 类里可以Animal.color访问
    public name: string// 公开 属性方法都能在类的外面调用
    public status?:string// 可选 子类不是一定要这个
    protected sex: string// protected可以在子类中访问,实例访问不到
    static age: number = 20 // 静态属性 直接通过类访问
    public readonly read: boolean // readonly只读修饰符只允许赋值一次
    constructor(name:string,sex: string) {
        // 外部入参
        this.name = name
        this.sex = sex
        // this.age = age// 改为访问静态成员“Animal.age”
    }
    // 外部访问 a.move()
    move(): void {
        console.log(this.name,this.sex)
        console.log(Animal.color,Animal.age)
    }
    // 外部访问 Animal.eat()
    static eat(): void {
        console.log(this.name)
        console.log(Animal.color,Animal.age)
    }
}
let a: Animal = new Animal('肥羊','女')// 动物实例a 
class Cat extends Animal {
    constructor(name: string,sex:string) {
        super(name,sex)// 绑定cat 改变this指向
    }
    move() {
        console.log('移动去')// 子类可以重写父类的方法
        super.move()
    }
}

模块

module X { 相当于现在推荐的写法 namespace X {)

// export导出
export const numberRegexp = /^[0-9]+$/; 
export class ZipCodeValidator implements StringValidator { 
        isAcceptable(s: string) {
        return s.length === 5 && numberRegexp.test(s);
    } 
}
// 或者
export { ZipCodeValidator }; 
export { ZipCodeValidator as mainValidator };// 别名

declare module "url" {
  export interface Url {
    protocol?: string;
    hostname?: string;
    pathname?: string;
  }
  export function parse(
    urlStr: string,
    parseQueryString?,
    slashesDenoteHost?
  ): Url;
}

接口 interface

接口是对类的行为进行约束 接口只声明和类型定义,类是代码复用

interface用来 约束 属性,函数,变量,类class

// 对象 接口可以用来设定或限制对象里面每个属性的类型 
interface IPerson {
        name?:string;// 可选属性
        date:string;
        sex:string;
        action():void;
        [propName:string]: any;   //任意属性  包括可选和必选属性
    };
let obj : IPerson = {必须和接口一致}

// 类和接口建立关联,靠implements建立 而不是:
interface UserInterface {
    name: string;
    say(): void
}
class User implements UserInterface {
    constructor(public name: string) {}
    say(): void {}
}
interface Ifon {
    readonly name: number;// 不可改变
    readonly age: number;
    color?: string;
    width?: number;
}

// 函数类型的定义 输入类型,输出类型
 //接口在函数中运用
interface IFn {
    (source: string, sub: string): boolean
}
let fn: IFn = function(src: string, sub: string):boolean {
    // 函数的参数名不需要与接口里定义的名字相匹配 :boolean可不写
    return true
}

泛型 Generics

泛型是指在定义函数、接口或类的时候,不预先指定具体的类型 使用的时候再指定类型的一种特性

// 泛型指基础类型或者对象比如Date

// 泛型约束数组
type T = (Date|number)//这里固定了2种 T表示任何类型 常用有T K V E Y N U 
let arr: Array<T> = [678, new Date()]

// 泛型约束函数function 任意类型的返回入参 保持统一,和any不一样
function fn<T> (...arg: T[]): T[] {
    return arg
}

// 结合接口 约束函数
interface Ifn {
    <T>(a:T,b:T):boolean
};
let fn:Ifn = function<T>(s1:T,s2:T):boolean{
    return s1==s2
};
fn(1,2)// 调用

// 泛型约束类class 类中定义泛型,泛型适用于多个类型
class Animals<T> {
    private data = {}
    n:T
    set(key: string, val: T): void {
        this.data[key] = val
        this.n = val;
    }
    get(key: string): T {
        return this.data[key]
    }
    add(n1:T):T{
        return n1
    }
}
var an = new Animals<string>()

function sum<T>(n1:T,n2:T):T[] {
    return [n1,n2]
}
sum<string>('1','2');
sum(3,5)  //类型推断

 //多个类型
function multi<N, S>(sum: [N, S]): [S, N] { 
    return [sum[1], sum[0]]; 
}
multi<number,string>([1, 'one']);

装饰器 @fn

启用experimentalDecorators
tsc --target ES5 --experimentalDecorators

// 装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上。
// 装饰器的语法是在要装饰的类/属性/方法前面使用@符号调用函数

// 装饰器函数 参数:target(类的prototype,static静态是类的构造函数),name(名字)还有少用的descriptor 也许会被返回
function fn(target: any) {
    console.log(target)
    target.num = 100
}

// 装饰器工厂
function fnbox(type: any) { // 这是一个装饰器工厂
    console.log(type) // 1/2
    return function(target: any) { // 这是装饰器
        if (type === 1) {
            target.name = '肥羊好'
        } else if (type === 2) {
            target.name = '哈哈哈'
        }
    }
}
// 装饰器组合
@f @g x

// 类装饰器 类构造函数监视,修改或替换类定义
@fn
@fnbox(1)// 装饰器会自动调用函数,把类传递过去
class Animals {
    constructor() {
        
    }
}

// 执行顺序:
// 方法和属性:@前面的先执行
// 方法和参数:参数先执行
// 参数:最后一个参数先执行
// 类:最后执行
@One()
class Hello {
    @Five()
    hello: string

    @Two()
    haha( @Three() p1: string, @Four() p2: string ) {
        console.log(p1, p2)
    }
}

组合 函数 类 接口 泛型

还有好多种组合。

//函数表达式
let es5fn = function<U>(n1:U,n2:U):U[] {
    return [n1,n2]
}
//ES6
let es6fn = <U>(n1:U,n2:U):U[] =>[n1,n2];
s6<string>('1','2');

//泛型的约束
interface ILengthNum {
    length:number;
}
function fn<T extends ILengthNum>(str:T):number {
    return str.length
};
fn('123');


// 2个接口 声音不通
interface ISing {
    singfn();// 唱歌 接口
}
interface Ispeak {
    singfn1(s:string):void;// 说话 接口
}
 //开关接口 继承 唱歌 说话 接口
interface ILight extends ISing,Ispeak{
    lightOn();// 开关
    lightOff();
}
//鹦鹉 鹦鹉的种类:1、和尚鹦鹉2、虎皮鹦鹉3、金刚鹦鹉
class Parrot {
    name:string
}
enum Color {
    Green, Red
}
//和尚鹦鹉 绿色,红色继承于鹦鹉 extends 能唱歌能说话implements
class Monkparakeet<T extends Color> extends Parrot implements ISing, Ispeak{
    private color: Color;  //私有属性
    name:string
    constructor(c:T){
        super();
        this.color = c;
    }
   singfn(){...};// 唱歌
   singfn1(){...};// 说话
}
//录音机被3个接口约束
class Recorder implements ILight {
    singfn(){...};// 唱歌
    singfn1(){...};// 说话
    lightOn(){...};// 开关
    lightOff(){...};
}
//接口继承类
// 移动这个行为,属于鹦鹉
interface IMove extends Parrot{
    name:string;
    movefn(){};
}
var o :IMove = {
    name:string
    movefn:function
}

//泛型在函数中的具体运用
//函数声明
function sum<T>(n1:T,n2:T):T[] {
    return [n1,n2]
}
//函数表达式
let sum1 = function<U>(n1:U,n2:U):U[] {
    return [n1,n2]
}
//ES6
let sum2 = <U>(n1:U,n2:U):U[] =>[n1,n2];
sum2<string>('1','2');

//泛型的约束
interface ILengthNum {
    length:number;
}
function len<T extends ILengthNum>(str:T):number {
    return str.length
};
len('123');

//泛型 接口 约束函数
interface IFn{
    <T>(a:T,b:T):boolean
}
let isFlag:IFn = function(x,y){
    return x==y
};
isFlag<number>(4,8)

//把泛型参数提前放在接口名上
interface IFn<T>{
    (a:T,b:T):boolean
}
let isFlag:IFn<number> = function(x,y){
    return x==y
};
isFlag<number>(4,8)

//另一种写法
let isFlag:IFn<number>;
isFlag= function(x,y){
    return x==y
};