智能合约开发——TypeScript 基础(全)

TS 准备

首先我们准备一个目录,使用 dos 进入到某目录,当然你直接 vs 打开终端执行也是没有问题的:
在这里插入图片描述
执行以下命令安装 typescrip(不用进入目录,直接安装即可):

npm install -g typescript

我是已经安装过了:

在这里插入图片描述
接着你可以初始化项目(这里需要进入文件夹了,毕竟是你的项目目录对吧,初始化项目就是以当前目录默认初始化):

tsc --init

在这里插入图片描述
此时你的目录中会出现一个 tsconfig 文件:
在这里插入图片描述

里面存储的是一些 ts 的config ,暂时不用理,接下来就可以开始 ts 的编程了。

一、TS 编译

安装好 nodejs 之后,新建一个 01.ts 文件:
在这里插入图片描述
编写代码:

console.log("HI") 

由于 ts 最终将会编译生成 js,你在 ts 中直接写 js 是没有问题的(并且ts不是一个全新的语言,是基于 js 的),在终端中输入 node 01.ts:

在这里插入图片描述

此时将会输出 HI~。

二、变量定义及编译

在 ts 变量定中需要指定的这个变量类型,这个是跟 js 大有不同,又或者说这该指定类型贯穿了整个 ts。

更改 01 代码:

let age: number = 18;
console.log(age)

以上代码中定义了一个 age变量,类型为 number,赋值为 18,此时在变量名之后有一个冒号,冒号右侧就是对应的这个变量的类型,最终使用等于号赋值为 18。

此时由于我们私用的是 ts 的语法,你直接使用 node 话会错误,需要使用 tsc-node 命令对 ts 文件进行编译:

在这里插入图片描述
若你使用 node 命令就不是编译了,此时将会报错:
在这里插入图片描述
使用 node 表示运行 js 文件,而不是 编译 ts 文件。

在创建一个变量的时候,也可以不指定类型,直接给定一个值,这个时候 ts 会完成类型的自动推导(跟go类似),这样就知道这个变量是什么值了,例如:

let age = 11;

三、生成 js 文件

在 ts 中,还可以直接使用 tsc 对 ts 编译生成 js 文件:
在这里插入图片描述
执行命令后,将会在当前目录下生成一个 js 文件,并且这个 js 文件是对应 ts 的 js 代码:
在这里插入图片描述
在这里插入图片描述
在此我们一定要注意, ts 你可以理解为是一种强制性的“规范语法”框架,在该“语法框架”下需要严谨的对某些动作进行处理,但最终的本质还是 js。

四、变量、数组

4.1 一般数据类型

ts 中类型有 number、string、boolean、symbol、数组、map 等,在此只介绍常见类型。

以下是对应这些类型的示例:

let age: number = 18;
let authorName: string = '1_bit';
let boolVal: boolean = true;//数组
let strs: string[] = ["1_bit", "blog", "author"];
let strOrNumber: (string | number)[] = ["1_bit", 11, "blog", "author", 22];

以上的示例中,主要看数组的定义,例如 let strs: string[] = ["1_bit", "blog", "author"];,在这段代码中 strs 是数组名,冒号后就是对应的类型约束,在此是 string,而方括号 “ [] ” 则表示这是一个数组,在等于号右侧则是这个数组中的值。

已经理解了基本的数组的 ts 数组,在查看对应的 strOrNumber 数组,在这个代码中,用圆括号包裹了 string 和 number 并且中间使用了“或”运算的 “ | ” 链接,这是表示这个数组中可以存储 string 以及 number 类型,所以在数组中可以看到 string 和 number 类型的数据都存在。

4.2 元组

学过 python 的小伙伴对元组应该很熟悉,在 ts 中的元组跟 python 中的不是很一样,在 ts 中定义的元组你可以理解为固长、固定类型的数组,可以指定某个位置的类型以及指定整个数组的长度,以下为元组示例:

let postion: [number, number];
postion = [0.45, 0.50];console.log(postion)
console.log(postion[0])

以上代码中 let postion: [number, number]; 为定义了一个元组,但是并没有进行初始化,接下来直接给 postion 定义了一个值[0.45, 0.50],随后使用 console.log 对其打印。

在此我们可以看到,数组的定义方式是之直接在变量的冒号后面使用一个类型加方括号“[]”定义一个数组,在元组中则是在方括号内编写对应的数值类型。

运行后结果如下:
在这里插入图片描述

4.3 any

在 ts 中不推荐使用 any 类型,你用了不就等于跟原本的 js 没啥区别了吗?若真的有必要使用 any 推荐临时使用,别贯穿项目。

以下是any 的错误示范(语法正确,使用错误):

let age: any;
age = "str";
console.log(age)
console.log(typeof age)

结果如下:
在这里插入图片描述

五、自定义类型(别名)

在 ts 中,若一个数组的类型经常使用,可以定义一个类型别名,在使用这个类型时即可简短的通过这个别名表示这个类型:

type StuT = (string | number)[]
let stus: StuT = ["1_bit", 13, "Xi", 26]

以上示例定义了一个 type 类型,这个类型为 (string | number)[] 表示是一个字符串与数组的数组类型,接着在下一行代码中直接创建了一个 stus 变量,指定为 StuT 类型,并且赋值有字符串和数字的值。

六、函数

6.1 基本函数

ts 语言中的自定义函数跟 go 中的有点相似,例如如下是一个 ts 中的自定义函数:

function sayHi(name: string, age: number): string {return "Hi " + name + " you " + age + " age";
}
let xiName: string = "Xi";
let xiAge: number = 19;
console.log(sayHi(xiName, xiAge));

在以上示例中 sayHi 是一个自定义函数,跟js 语法一样,使用function 定义一个函数,在 sayHi 函数中有两个参数,一个是 name 还有一个是 age,name 参数是一个 string 类型,age 是一个 number 类型,参数的声明在此也是不同的,使用了 ts 的语法;还有一点不同的是在参数之后使用一个冒号说明了当前函数的返回值为一个 string,在此需要注意,这是 ts 的语法。

接着我创建了两个边路 xiName 以及 xiAge,用此当做参数传入到 sayHi 之中,此时使用 ts-node 命令编译运行我们的 ts 文件:
在这里插入图片描述

6.2 箭头函数

函数的编写还有另外一种使用箭头函数的方式:

const sayHi = (name: string, age: number): string => {return "Hi " + name + " you " + age + " age";
}
let xiName: string = "Xi";
let xiAge: number = 19;
console.log(sayHi(xiName, xiAge));

6.3 箭头函数加强版

函数还有另外一种定义方式,可能大家都不是特别想去学习:

const sayHi: (name: string, age: number) => string = (name, age) => {return "Hi " + name + " you " + age + " age";
}

其实这个形式可以看成两个部分:
在这里插入图片描述
其中前半部分是为这个 sayHi 声明一个类型,这个 sayHi 的类型是 (name: string, age: number) 由于需要指定这个函数返回值,所以使用 => string 表示当前函数返回值为 string。

接着我们再看第二个部分:
在这里插入图片描述
这一部分就直接当做函数的内容即可,而 (name, age) 表示这个函数接收两个参数,把之前所说明的 name 和 age 两个变量传入到函数,所以在此处并不用使用类型对其进行约束,在之前已经做好约束了,最后箭头函数右侧则是函数体。

函数返回值若为空则使用 void。

6.4 可选参数

可选参数在 ts 中表示这个参数可传或不传,非必须参数,例如我们现在修改以上示例完成需求“姓名必传、年龄和身高为可选,传入年龄或身高需要对应的对其进行显示”。

若完成这个需求那么必然会有一个函数对某个值进行判断,此时做一个检测的函数:

function isUndefine(arg: (number | string | undefined)): boolean {let check: boolean = true;if (!arg) {check = false;}return check;
}

以上检测 agr 参数,参数因为需要时 number、string、undefined 类型的其中一个,所以在此处设定了这个参数的类型范围,接着有一个 Boolean 的返回值,在函数体中给了一个变量 check 为 Boolean,初始值为 true,只要 arg 不存在那么久 fase 即可,最后返回 check。

接着我们修改 sayHi 函数,修改后调用检测参数的函数,完成内容的拼接:

const sayHi: (name: string, age?: number, height?: number) => string = (name, age, height) => {let sayStr = 'Hi ' + name;if (isUndefine(age)) {sayStr += " you " + age + " age";}if (isUndefine(height)) {sayStr += " you " + age + " age " + "height " + height;}return sayStr;
}

此时两个 if 判断 age 或者 height 是否存在,随后进行拼接即可,最后返回了sayStr 这个字符串。

在这里我们可以看到,参数 age、height 在参数名后添加了一个问号,这个问号就是表示可选参数。

最终完整代码如下:

function isUndefine(arg: (number | string | undefined)): boolean {let check: boolean = true;if (!arg) {check = false;}return check;
}const sayHi: (name: string, age?: number, height?: number) => string = (name, age, height) => {let sayStr = 'Hi ' + name;if (isUndefine(age)) {sayStr += " you " + age + " age";}if (isUndefine(height)) {sayStr += " you " + age + " age " + "height " + height;}return sayStr;
}
let xiName: string = "Xi";
let xiAge: number = 19;
console.log(sayHi(xiName, xiAge, 170));

最终传入不同的参数将会显示不同的结果:

在这里插入图片描述

七、对象

在 ts 中使用对象分为声明和定义,声明就像类型一样进行使用,定义则是赋予这个对象的值:

let stu: {name: string;age: number;height: number;getName(): string;getAge(): number;setName(name: string): void;setAge(age: number): void;} = {name: 'Xi',age: 11,height: 170,setName(name) {this.name = name;},setAge(age) {this.age},getName() {return this.name;},getAge() {return this.age},
}stu.setName("1_bit")
console.log(stu.getName())

以上实例中定义了一个 stu 的对象,其中包含 name、age、height 变量以及 getName 等方法,这些都可以看做是这个对象的“类型”,随后赋值为这些“类型”的初始化,并且设定函数的实现。

在此一定要注意,你既然声明了,那就必须要实现(若删除一个成员变量的初始化),否则会报错:
在这里插入图片描述
运行结果如下:
在这里插入图片描述

八、类

8.1 类的基本使用

在 ts 中定义一个类方式很简单,使用 class 例如如下示例:

class Stu {public readonly name: string;public age: number;private nickname: string = '';private readonly color = 'yellow';constructor(_name: string, _age: number) {this.name = _name;this.age = _age;}public setNickName(_nick: string) {this.nickname = _nick;}public getNickName() {return this.nickname;}
}

以上示例中使用 class 创建了一个 stu 类,在这个类中定义了几个成员变量,在这几个成员变量中使用了 public、private 对其进行修饰,public 表公开都可以调用,private 私有,自由类内部可以调用,除了这些常规的修饰之外还有一个 readonly,readonly 表示当前字段不允许修改,若你想对其进行改动那么将会报错:
在这里插入图片描述
在此还需要注意,这些变量你都需要对其进行初始化,否则将会报错。

在类中还有一个构造方法,ts 是支持构造方法的;在使用成员变量时需要使用 this 对其指向,直接使用变量名将会出错。

ts冷笑话:在 class 中创建“函数”不需要使用 function,因为他是方法。

接着创建一个对象:

const XiaoMing = new Stu("XiaoMing", 18);
XiaoMing.setNickName("MM");
console.log(XiaoMing.getNickName());

接着使用 tc 命令编译运行:

在这里插入图片描述

在 ts 中类的继承使用 extends:

class Stu1 extends Stu {public getName(): string {return this.name}
}

继承后在 Stu1将会拥有 Stu 的成员变量和方法,使用和正常一个对象使用一致:

const XiaoMing1 = new Stu1("XiaoM", 18);
console.log(XiaoMing1.getName());

8.2 函数重载

8.3 类的兼容性

以下是一个示例,在 ts 中相同成员变量的类可以互相兼容:

class Stu1 {name: string;height: number;constructor() {this.name = "xiaoM";this.height = 170;}
}class Stu2 {name: string;height: number;constructor() {this.name = "xiaoY";this.height = 160;}
}const xiaoY: Stu1 = new Stu2()

若此时 Stu2 中多了一个成员变量呢:
在这里插入图片描述

此时 Stu1 还是兼容于 Stu2 的,少的可以兼容于多的,若反过来是不可以的:
在这里插入图片描述
当然多个方法也没问题:
在这里插入图片描述

九、接口

9.1 接口的一般使用

在 ts 中支持接口,使用关键字 interface:

interface stuI {height: number;name: string;getName(): string;
}

以上定义了一个接口,若需要某些变量为该接口类型,那么就需要对接口中的变量进行初始化和实现方法:

let stu: stuI = {height: 170,name: "1_bit",getName() {return this.name;}
}

实现方法很简单,就是 let 一个变量后指定接口为类型,随后使用花括号对其中的内容进行初始化。

接口还可以继承,例如如下示例:

interface stuI1 extends stuI {color: string,getHeight(): number
}

以上 stuI1 继承 stuI,并且继承了其中的内容,在 stuI1 接口中可以为接口本身编写 stuI1 的内容。

使用也如下使用示例(需要完全实现接口、父接口的中的内容):

let stu1: stuI1 = {height: 170,name: "1_bit",color: "yello",getName() {return this.name;},getHeight() {return this.height}
}

最后调用:

console.log(stu.getName());
console.log(stu1.getHeight());

在这里插入图片描述

9.2 交叉类型与同名成员变量

交叉类型其实就是多个接口进行合并,如下示例:

interface BBB { name: string }
interface CCC { age: number }
interface DDD { height: number }type BCD = BBB & CCC & DDD
let val: BCD = {name: 'ccc',age: 123,height: 12121
}

交叉类型直接使用 & 对某个类型进行定义即可,之后的变量在使用这个类型的时候就必须实现这些接口中的内容。

若接口中有同名,那么那么变量就是 never 类型,表示不可能,永远不可能。

9.2 交叉类型与同名函数参数

在同名函数中的参数同名但类型不同的情况下可以理解为同时兼容于两个类型,例如:

interface CCC {age: number;getVl(key: number): string
}
interface DDD {height: number;getVl(key: string): string
}

以上两个接口新增了一个同名方法 getVl,参数同名却参数类型不同,此时就可以当成是 getVl(key: (number | string)),例如如下代码:

type BCD = BBB & CCC & DDD
let val: BCD = {name: 'ccc',age: 123,height: 12121,getVl(key: (number | string)) {console.log(key)return "1";}
}val.getVl(233);

十、泛型 后面有时间再补

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/285823.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

利用Signalr实现手机端App扫码登录web页面

实现原理: 1、web登录页面,利用jquery.qrcode展示一个随机生成的登录码的二维码; 2、手机App扫描二维码取得登录码; 3、手机App将本地用户id登录码通过api提交服务器; 4、服务器api,收到手机App请求&am…

【ArcGIS风暴】ArcGIS栅格影像(NDVI)归一化处理的两种方法精解

【ArcGIS遇上Python】ArcGIS批量处理栅格影像(NDVI)归一化完整案例代码 图像归一化是指对图像进行了一系列标准的处理变换,使之变换为一固定标准形式的过程,该标准图像称作归一化图像。 原始图像在经历一些处理或攻击后可以得到多种副本图像,这些图像在经过相同参数的图像…

以小见大:一个领域建模的简单示例,理解“领域驱动”。

背景:航空公司为了确保飞行路线不发生冲突,需要开发一款飞行路线管理软件。过程:我们先去找这个领域的专家,自然是作为平时管理和维护机场飞行秩序的工作人员;我们第一个目标就是与他们沟通,也许我们并不能…

【ArcGIS遇上Python】ArcGIS批量处理栅格影像(NDVI)归一化完整案例代码

文章《ArcGIS栅格影像(NDVI)归一化处理的两种方法精解》详细介绍了ArcGIS中进行NDVI影像归一化处理的两种方法,但是无法批量进行,本文就放大招用Python实现批量NDVI归一化处理,大大提高了工作效率,还不赶快Get了? 完整Python代码: import arcpy from arcpy import env…

Spark1.0.0 属性配置

1:Spark1.0.0属性配置方式Spark属性提供了大部分应用程序的控制项,而且能够单独为每一个应用程序进行配置。在Spark1.0.0提供了3种方式的属性配置:SparkConf方式 SparkConf方式能够直接将属性值传递到SparkContext;SparkConf能够对…

Lync Server 2010迁移至Lync Server 2013部署系列 Part1: 扩展AD架构

由于最近直在忙Lync 升级,好久没有更新博客了,今天开始将对最近做的Lync Server 2010迁移至Lync Server 2013项目做一个系列的部署操作更新,希望能给即将在企业中部署的兄弟们有所帮助,在这个测试环境中,企业 前端池共…

Hello Playwright:(7)模拟键盘和鼠标

尽管在上一节中,我们已经能够通过FillAsync或ClickAsync来实现输入和点击元素。但是,还有其他场景,我们必须模拟用户使用键盘、鼠标与页面交互。例如在线文档:Page.Keyboard 对象Keyboard提供用于管理虚拟键盘的 API,它…

【ArcGIS遇上Python】Python批量将多个文件夹下的多个影像数据镶嵌至新栅格

ArcGIS虽然可以实现一次多个影像同时参与,拼接成一个整的影像,但是通常情况下,多个影像并不在同一个文件夹下,这样拼接的时候需要逐个手动进行添加,如果数据量大的话,跟不就不可取,针对这一问题,本文采用Python,实现将多个文件夹下的多个影像拼接,高效快速。 我们以…

2019全球开发者调查:仅2%的人996,Python并不是最受喜爱的语言

导读:开发者社区正在发生哪些变化?Stack Overflow 的最新调查获得了一些预料之外的结果:Java 语言开发者的平均收入不到 35 万元人民币,成为了收入最低的群体;另一方面,人工智能领域流行的 Python 并不是最…

一般地

2019独角兽企业重金招聘Python工程师标准>>> 1.EO的Updatable属性默认为Always,基于EO创建的VO也是。而基于SQL创建VO的Updatable属性默认为Never,如果要修改(例如将VO拖至页面生成Form用于新增),则需将该属…

最新!2019 年中国程序员薪资生存调查报告出炉

此调查,是对北京、上海、广东和浙江等全国 29 个省、直辖市及特别行政区的 26W 优秀程序员进行了一次详细的调查,形成本报告。 根据中国互联网络信息中心(CNNIC)近日发布第 43 次《中国互联网络发展状况统计报告》。截至 2018 年 …

快速掌握 ASP.NET 身份认证框架 Identity - 登录与登出

推荐关注「码侠江湖」加星标,时刻不忘江湖事这是 ASP.NET Core Identity 系列的第三篇文章,上一篇文章讲解了如何在 ASP.NET Core Identity 中实现用户注册。那么,这篇文章讲一讲如何在 ASP.NET Core Identity 中实现用户的登录与登出。点击上…

C语言试题七十九之请编写函数实现自然底数 e=2.718281828

📃个人主页:个人主页 🔥系列专栏:C语言试题200例目录 💬推荐一款刷算法、笔试、面经、拿大公司offer神器 👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 请编写函数…

如何创建NFT并OpenSea上展示《alchemy How to Develop an NFT Smart Contract》译

翻译:1_bit 原文:https://docs.alchemy.com/docs/how-to-develop-an-nft-smart-contract-erc721-with-alchemy 注:英文不好各位多多担待 1.如何使用 Alchemy 开发一个 NFT 智能合约 在你第一次使用 solidity 时开发一个智能合约部署在区块…

Jmeter之Bean shell使用(二)

上一篇Jmeter之Bean shell使用(一)简单介绍了下Jmeter中的Bean shell,本文是对上文的一个补充,主要总结下常用的几种场景和方法,相信这些基本可以涵盖大部分的需求。本节内容如下: 一、操作变量 二、操作属性 三、自定义函数 四、…

【ArcGIS风暴】ArcGIS中国地表覆盖数据GlobeLand30预处理(批量投影、拼接、掩膜提取)附成品下载

结果示意图: GlobeLand30是30米空间分辨率全球地表覆盖数据,目前可供下载的有3年的数据:2000-2010-2020。本文主要讲解在ArcGIS10.6平台下进行GlobeLand30的预处理操作,主要预处理步骤包括:批量分幅投影转换、批量分幅…

Asp.Net MVC4入门指南(9):查询详细信息和删除记录

在本教程中,您将查看自动生成的Details和Delete方法。 查询详细信息和删除记录 打开Movie控制器并查看Details方法。 ?Code First 使得您可以轻松的使用Find方法来搜索数据。一个重要的安全功能内置到了方法中。方法首先验证Find方法已经找到了一部电影&#xff0c…

漫画:什么是架构师?

于是,小灰去向大黄请教 这是有关未来的故事: 从前,有一个赶路的人路过一片工地,看到三个年轻人在工地上搬砖。 于是,他问其中一个人: 于是,他又问了第二个人: 于是,他又问…

Andoroid之BottomNavigationView右上角添加红点布局和自动跳转到底部具体第几个Tab

一、需求 BottomNavigationView右上角添加红点布局和自动跳转到底部具体第几个Tab 我们知道BottomNavigationView是在google material里面的组件 github地址如下: https://github.com/material-components/material-components-android 二、效果图片爆照 三、BottomNaviga…

FileSystemWatcher监听文件是否有被修改

作用:监听文件系统更改通知,并在目录或目录中的文件更改时引发事件。 需求:监听特定文件是否修改,然后做出相应的操作。 方法: ①利用一个线程,一直去查找该指定的文件是否有被修改,如果修改则操…