Typescript 入门

Typescript

环境

有npm的情况下,直接

npm config set registry https://registry.npmmirror.com   //使用国内镜像
npm install -g typescript
tsc -v              //检查版本

文件编译

tsc helloworld.ts
//会生成helloworld.js
再使用node helloworld.js 即可运行

对象

一个对象是包含一组键值对集合的实例。值可以是标量值或函数,甚至是其他对象的数组。
划重点,ts的对象只是一组键值对集合的实例,和java、c#这些需要通过类实例化后的对象不同。
示例

var dog:dog_act={
    bark():void{
      console.log("bark!!!!")
    },
    dog_act:"wanwan"
}

dog.bark();

对象声明用逗号隔开,属性都是键值对格式,调用属性时直接调用即可。

class Animal implements animal_base,animal_base2{
    atype:String=""
    constructor(a_type:String){
        //this is construct
        this.atype=a_type
    }
    animal_do(){
        if(this.atype == "dog" ){
            console.log("run")
        }else{
            console.log("swim")
        }
    }
     static do():void{
        console.log("use static")
    }
}

Animal.do();
var a1=new Animal("dog");
a1.animal_do();

ts的类实例后称为实例对象,不要跟对象混淆。
可以使用构造函数,但不允许多重构造函数
实例化和内部使用都中规中矩,静态结构直接使用类名调用就好了。

作用域

  • private:只能在类中调用,实例对象也没法调用.The private modifier limits the visibility to the same-class only. When you add the private modifier to a property or method, you can access that property or method within the same class. Any attempt to access private properties or methods outside the class will result in an error at compile time.
  • public:The public modifier allows class properties and methods to be accessible from all locations. If you don’t specify any access modifier for properties and methods, they will take the public modifier by default.
  • protected:The protected modifier allows properties and methods of a class to be accessible within same class and within subclasses.使用extends继承的子类也可以使用父类protected 修饰的类型。但与private类似,只能在类中调用,任何外部调用都将导致编译错误

constructor

构造器
如果父类中声明了构造函数,子类在声明构造函数时必须在自身的构造函数中使用super()以完成父类的初始化。

class woman{
    constructor(private name:string){

    }
    public age:number;
    public  fun1(num:number):boolean{
        if(num>3)
        return true
        else
        return false
    }
    protected fun2_private(){
        if(this.name!=null){
            console.log(this.name+"the age is "+this.age)
        }
    }
    test(){
        console.log(this.name+"the age is "+this.age)

    }
}

class mylove extends woman{
    constructor(){
        super("jin");
    }
    public hhh(){
        this.fun2_private()
    }
    
}

如上,当父类构造函数有参数时,也需要在子类中代入。

一个语法糖是在construct的参数中,可以使用public/private之类的修饰符号修饰,这样相当于在woman 类中添加了private name:string,当实例化woman时,name字段会自动成为woman的一个属性,内部可以用this.name,外部可以直接调用(在public修饰的情况下)

接口

interface interface_name { 
}

接口用于规范其他结构的行为,内部只声明,不实现。
eg:

interface animal_base3{
    blood:boolean;
}

接口与接口

一个接口可以多继承自其他接口,相当于接口叠加了其他接口的规范

interface animal_base3{
    blood:boolean;
}

interface animal_base{
    breath():string;
    eat():void;
    eye:number;
}

interface animal_base2 extends animal_base3,animal_base {
    leg:number|any;
    useforhuman:boolean;
}

对象与接口

对象章节,知道是ts的对象一个键值对的集合,对象可以继承一个接口,不支持多继承
语法(:)

var object:interface_name={
    //interface implement
}

示例

interface dog_act{
    bark():void,
    dog_act:String
}

var dog2:dog_act={
    bark():void{
        console.log("wanwan")
    },
    dog_act:"sleep",
}

对象一旦继承接口,则必须实现接口的所有属性。且不能创建除了接口声明之外的其他属性。如上示例,如果dog2中自定义了一个hhh:“jfise”,会报

Type '{ bark(): void; dog_act: string; hhh: string; }' is not assignable to type 'dog_act'.
  Object literal may only specify known properties, and 'hhh' does not exist in type 'dog_act'.

由此可以看出接口对于ts的对象是一个强规范。

类与接口

类可以多继承接口
语法(implements)

class Class_name implements interface1_name,interface2_name,...{}

示例

interface animal_base{
    breath():string;
    eat():void;
    eye:number;
}
interface animal_base2 extends animal_base3,animal_base {
    leg:number|any;
    useforhuman:boolean;
}

class Animal implements animal_base,animal_base2{
    atype:String=""
    constructor(a_type:String){
        //this is construct
        this.atype=a_type
    }
    breath(): string {
        throw new Error("Method not implemented.");
    }
    eat(): void {
        throw new Error("Method not implemented.");
    }
    eye: number;
    leg: any;
    useforhuman: boolean;
    blood: boolean;
    animal_do(){
        if(this.atype == "dog" ){
            console.log("run")
        }else{
            console.log("swim")
        }
    }
}

跟其他语言一样,只要实现了接口的功能即可,没有对象那么严格。
多说一句,类这样继承接口,是为了在类对象的传递时,能够确认到实现了某些必要的功能(协议等等),所以接口从一开始,就是为了规范

参考

TypeScript 接口

泛型

软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。
实际使用,主要记住一个语法规则即可
<T,…>(T…)
其中<>中的参数,声明了这个结构(接口,函数,类)可能会用到的数据类型,这个参数所指的类型,是通过()匹配出来的。
一个简单的例子

function identities<T, U>(arg1: T, arg2: U): void {
    console.log(arg1 + ": " + typeof (arg1));
    console.log(arg2 + ": " + typeof (arg2));
}

identities(3,"hhh")

上面的例子中,运行的示例identities(3,"hhh")也可以改用identities<number,String>(3,"hhh")来调用。
注意(arg1:T,arg2:U)用于匹配输入结构(3,“hhh”),通过这里,系统自动判断出T=number,U=String.为了能够在function中使用这两个判断出来的参数,需要在<>中做好标记,这个标记可以不按照顺序<T,U>或者<U,T>都可以,<>的唯一作用只是为了标记出要使用的数据类型。而被标记出来的数据类型,可以在结构的任何可能的地方用上,甚至可以包括结构的返回类型,如上的声明,可以改成function identities<T, U>(arg1: T, arg2: U): T {return arg1;}

泛型是为了让结构能够在其他数据类型的情况下也能够起作用,你当然可以直接使用any作为输入参数,之后再去转,但泛型这种做法更加高效。
如果以上可以理解 <>用于声明要用到的数据类型,()用于匹配数据类型,那对于下面的泛型的示例,就不难分析了。
直接上code

泛型约束(感觉没什么作用)

interface interface_1 {
    num1: number
    str1: String
}

interface interface_2 extends interface_1 {
    num2: number
}

function fun_1<T extends interface_1>(arg: T): void {
    console.log(arg.num1)
}

var sample_1: interface_2 = {
    num2: 0,
    num1: 0,
    str1: "hhh"
}

fun_1(sample_1)
fun_1({ num1: 2, str1: "hhh" })
//唯一能想到的有用的使用方式,杂交怪了都,这样实际上就称不上完全重用,被接口约束了
function fun_2<A, B extends interface_1>(arg: B, arg2: A): void {
    console.log(arg.num1 + typeof (arg2))
    if (typeof (arg2) == "number")
        console.log("this is number type")
}

fun_2({ num1: 1, str1: "str1" }, 2)

类&接口&泛型测试

interface interface_5<T> {
    getChildren(element: T): void
    getParent(element: T): void
    getTreeItem(element: T): void
    resolveTreeItem(elemnet: T): void
}

class sample_1_class {
    num1: number = 0
    constructor(arg: number) {
        this.num1 = arg
    }
    do_something(): void {
        console.log("doing...")
    }
    static static_do(): number {
        console.log("static doing...")
        return 0;
    }
}

class test implements interface_5<sample_1_class>{
    getChildren(element: sample_1_class): void {
        throw new Error("Method not implemented.")
    }
    getParent(element: sample_1_class): void {
        throw new Error("Method not implemented.")
    }
    getTreeItem(element: sample_1_class): void {
        throw new Error("Method not implemented.")
    }
    resolveTreeItem(elemnet: sample_1_class): void {
        throw new Error("Method not implemented.")
    }

}

在泛型里使用类类型(终极杂交怪,看不懂算了)

console.log("<<<<")
class class_2 {
    arg3: String="9";
    arg4: number;
    class_2_do(arg:any):void{
        console.log("class_2 do"+arg)//使用any来接受任何参数
    }
}

//{ new(arg: B): T; prototype: { arg3: K ;}; }=>构造签名,A需要包含签名的属性,可以有其他的属性,但这上面的构造签名的内容必须满足,当做类来看就好了
//使用fun_4的时候,要能够满足传入的值(A,arg2)按照一定的规则,注意A是类,可以看作就是T,不是类对象
function fun_4<T extends class_2, K,B>(A: { new(arg: B): T; prototype: { arg3: K ;}; }, arg2: B): T{
    console.log(typeof(A))
    new A(arg2).arg3//arg2的类型必须和arg一致,某种程度上算是暴露了arg的类似,但是没必要
    new A(arg2).arg4//仅仅是class_2的一个属性
    new A(arg2).class_2_do(arg2)//这限制A必须继承自class_2,并且可以处理参数arg2
    A.prototype.arg3//可以直接调用,但是没有意义,此外arg3需要有赋值,如果class_2只是声明了arg3没有赋值,那下面的打印K=undefined
    console.log("the object of A.arg3 is K="+typeof(new A(arg2).arg3))//可以使用arg3的参数类型做一些事情,这里相当于直接把A的继承类class_2的属性arg3的类型暴露出来
    return  new A(arg2)//这里返回的类似定义为T
}

class class_1 extends class_2 {
    arg1: number
    constructor(arg:number){
        super();
        this.arg1=arg
    }
    
    fun_1():void{
        console.log("the num "+ this.arg1)
    }
}

fun_4(class_1,4).fun_1()
fun_4(class_1,5).fun_1()

console.log(">>>>")

打印输出为

<<<<
function
class_2 do4
the object of A.arg3 is K=string
the num 4
function
class_2 do5
the object of A.arg3 is K=string
the num 5
>>>>

其中()内的表达式,new(arg:B)等于construct(arg:B),prototype内的数据理解为一个class可以包含的常用数据结构

在泛型里使用类类型 official demo(官方的更好理解点maybe)
class BeeKeeper {
    hasMask: boolean;
}

class ZooKeeper {
    nametag: string;
}

class Animal_1 {
    numLegs: number;
}

class Bee extends Animal_1 {
    keeper: BeeKeeper;
}

class Lion extends Animal_1 {
    keeper: ZooKeeper;

}

function findKeeper<A extends Animal_1, K, B>(a: { new(arg: B): A; prototype: { keeper: K } }): K {

    return a.prototype.keeper;
}

findKeeper(Lion).nametag;  // typechecks!

正则

常用规则

  • g:全局匹配
  • i:不区分大小写
  • *:让前一个重复匹配大于0次
  • .:匹配除换行之外的单个字符(包括空格)
  • [0-9]:匹配一个数字
  • [a-z]/[A-Z]:匹配一个字母小写/大写
  • {n}:前一个匹配项目重复n次
  • {n,}:匹配项目重复至少n次
  • {n,m}:匹配项目重复n次到m次

构建正则的方式有两种

  1. 直接使用正则对象
    var patt=/pattern/modifiers;
    示例:
    var reg_10=/[0-9]{4}\s\w*/g
    console.log(reg_10.exec(str_2))
    
    其中
    pattern(模式) 描述了表达式的模式
    modifiers:用于指定全局匹配、区分大小写的匹配和多行匹配
  2. 创建RegExp对象
    var patt=new RegExp(pattern,modifiers);
    示例
    var reg_9=new RegExp("[0-9]{4}\\s\\w*","g")
    console.log(reg_9.exec(str_2))
    
    使用g变量的,匹配一次后再次调用匹配会自动返回下一个匹配项(如下实例的reg_8)
    推荐对于有重复匹配需求的,可以写成类似如下的方式
     let ary_1:number[]=[23,33,45,73,34,23,33,33]
    
     let reg_1= /233/gi;//var patt=/pattern/modifiers;
     console.log("the array is "+ary_1.toString().replace(/,/g, ""))
     let match;
    
     while(match=reg_1.exec(ary_1.toString().replace(/,/g, "")))
     {
         console.log("the res is "+match+"the position is "+match.index)
     }
    

上面两种方式对str_2的正则匹配效果一致,注意后者需要使用转义就好了。
其他详细匹配方式示例如下

let str = "1111-222222266644";
let str_2 = "This is 6886 world, i will try tryy tzy my best.This is 6886 world"

let reg_1= /\d{4}-\d{7}/g;//var patt=/pattern/modifiers;
console.log(reg_1.exec(str))

//当使用构造函数创造正则对象时,需要常规的字符转义规则(在前面加反斜杠 \)
var reg_2=new RegExp("\\d{4}-\\d{5}","g")
console.log(reg_2.exec(str))

var reg_3=new RegExp("[A-Z][a-z]is\\s\\w*.[0-9]*","g")
console.log(reg_3.exec(str_2))

var reg_4=new RegExp(".*")//由于.是匹配任何字符,*是重复,这使得匹配结果是整行,贪婪模式
console.log(reg_4.exec(str_2))

var reg_5=new RegExp("^Th\\w*\\s\\w*.[0-9]*","g")//^符号是从字符串开始匹配,只能放在最前面,匹配也由这里作为锚点往下面继续匹配
console.log(reg_5.exec(str_2))

var reg_6=new RegExp("..\\w* \\w* [0-9]* world$")//$符号是从字符串末尾开始匹配,只能放在最后,匹配也从这里作为锚点向前匹配
console.log(reg_6.exec(str_2))

var reg_7=new RegExp(" [0-9]* ","g")//不加空格无法匹配到数字 ' 6886 '
console.log(reg_7.exec(str_2))

var reg_8=new RegExp("\\bt[a-z]*y\\b","gi")//通过\b匹配第一个t开头,y结尾的单词
console.log(reg_8.exec(str_2))           //'try'
console.log(reg_8.exec(str_2))          //g参数会继续匹配下一个t开头,y结尾的单词 'tryy'

var reg_9=new RegExp("[0-9]{4}")
console.log(reg_9.exec(str_2))

var reg_10=/[0-9]{4}\s\w*/g
console.log(reg_10.exec(str_2))

参考

正则表达式中参数g、i、m的作用(share)
正则表达式 \b

Promise

Js Promise 参考
typescript 使用promise 的方式类似,但对于resolve的值,可以使用Promise泛型的方式将其声明会返回的类型

var p1 = new Promise<string>((ok, ng) => {
    // ok("the case finish")
    ng("the case fail")
})
p1.then(
    res1 => {
        console.log("the res is " + res1)

    },
    res2 => {
        console.log("the res is " + res2)
    }
)

这里的res1会被自动识别为string,或者使用这种方式

var p2=new Promise((ok:(value:number)=>void,ng)=>{
    ok(1)
    ng("fail")
})

p2.then(res => {
    console.log("the res is " + res)
}).catch(e => {
    console.log("the res is " + e)
})

promise 特殊用法

在看vscode 插件开发时,发现Map集合的值可以通过promise先创建,之后通过resolve值可以作为返回调用。



let call_back=new Map<number,(res:any)=>void>();
const index:number=1;

//延迟函数
function timeoutPromise(interval) {
    return new Promise((resolve, reject) => {
        setTimeout(function () {
            resolve("done")
            console.log("2s ...")
            // resolve("done");
        }, interval);
    });
}

async function main_fun(){
    var p=new Promise(resolve=>{
        call_back.set(index,resolve)//这里虽然在call_back 中增加了index,resolve 的键值对,但是resolve实际是没有东西的
    })
    console.log("config promise ok")

    await timeoutPromise(2000)//使用await让调度使用单线程

    var c1=call_back.get(index) 
    c1?.("test")                //在这里才将call_back的index键赋值,在这之后p的resolve 为字符串"test"

    console.log("end of set value")
    await p.then(e=>{console.log("the res is "+e)}) //此时可以将resolve 打印
}

main_fun()

输出如下

config promise ok
2s ...
end of set value
the res is test

使用了Map,tsc 编译要加上-t es6
promise的resolve的定义为
(parameter) resolve: (value: unknown) => void,这和call_back(Map)定义的值类型是相同的,resolve本质是一个函数,以上的例子在构建Promise后等待被赋值并捕获该值,可以用在callback检测上。即callback返回后赋值了,await P(promise)可以继续运行下去

参考

如何在Typescript中定义Promise的返回值类型
TypeScript 和 promise

项目工程代码

helloworld.ts

// var str = 'hhhhh' 
// var str2:string = <string> <any> str   //str、str2 是 string 类型
// console.log(str2)
interface animal_base{
    breath():string;
    eat():void;
    eye:number;
}
interface animal_base2 extends animal_base3,animal_base {
    leg:number|any;
    useforhuman:boolean;
}

interface animal_base3{
    blood:boolean;
}

interface dog_act{
    bark():void,
    dog_act:String
}
interface dog_act2{
    eatshit():void;
}

interface dog_act3{
    eatshit():void;
}

var dog:dog_act={
    bark():void{
      console.log("bark!!!!")
    },dog_act:"wanwan"
}

var dog2:dog_act={
    bark():void{
        console.log("wanwan")
    },
    dog_act:"sleep",
}

var dog3:animal_base2={
    leg: undefined,
    useforhuman: false,
    blood: false,
    breath: function (): string {
        throw new Error("Function not implemented.");
    },
    eat: function (): void {
        throw new Error("Function not implemented.");
    },
    eye: 0
}

dog.bark();

class Animal implements animal_base,animal_base2{
    atype:String=""
    constructor(a_type:String){
        //this is construct
        this.atype=a_type
    }
    breath(): string {
        throw new Error("Method not implemented.");
    }
    eat(): void {
        throw new Error("Method not implemented.");
    }
    eye: number;
    leg: any;
    useforhuman: boolean;
    blood: boolean;
    animal_do(){
        if(this.atype == "dog" ){
            console.log("run")
        }else{
            console.log("swim")
        }
    }
    static do():void{
        console.log("use static")
    }
}
Animal.do();

var a1=new Animal("dog");

a1.animal_do();

build.sh

tsc helloworld.ts
if [[ -e helloworld.js ]]
then
    node helloworld.js
    rm helloworld.js
fi
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值