2.TypeScript 基础入门(二)
变量类型的那些事
1.基本注解
类型注解使用:TypeAnnotation
语法。类型声明空间中可用的任何内容都可以用作类型注解。
const num: number = 123;
function identity(num:number):number{
return num;
}
加入注解以后会报错的写法:
const num: number = 123;
function identity(num: number): number {
const num1 = '123'
// 返回的不是 number 报错
return num1;
}
const num1 = '123'
// 参数不是 number 报错
identity(num1)
2. 原始类型
Javascript
原始类型也同样适用于 TypeScript
的类型系统。因此,string
, number
,boolean
也可以被用作类型注解:
let num: number;
let str: string;
let bool: boolean;
num = 123;
num = 123.45;
num = '123'; //Type '"123"' is not assignable to type 'number'
str = '123';
str = 123; //Type '123' is not assignable to type 'string'
bool = true;
bool = false;
bool = 'false';//Type '"false"' is not assignable to type 'boolean'.
3. 数组
TypeScript
为数组提供了专用的类型语法,因此你可以很轻易的注解数组。它使用后缀[]
,接着你可以根据需要补充任何有效的类型注解(如:boolean[]
)。它能让你安全的使用任何有关数组的操作,而且它能放置一些类似赋值错误类型给成员的行为。
你有两种定义数组的方式:
第一种,你可以在元素类型后面接上[]
,表示由此类型元素组成的一个数组:
let list:number[] = [1,2,3]
第二种方式是使用数组泛型,Array<元素类型>
:
let list: Array<number> = [1,2,3]
一个具体的栗子:
const boolArray: boolean[];
boolArray = [true, false];
console.log(boolArray[0]); // true
console.log(boolArray.length); // 2
boolArray[1] = true;
boolArray = [false, false];
boolArray[0] = 'false'; // Error
boolArray = 'false'; // Error
boolArray = [true, 'false']; // Error
4.元组
元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。比如,你可以定义一对值分别为string
和number
类型的元组。
// 声明一个元组类型
let x: [string, number];
// 初始化赋值
x = ['hello', 10]; // OK
// 初始化错误
x = [10, 'hello']; // Error
当访问一个已知索引的元素,会得到正确的类型:
console.log(x[0].substr(1)); // OK
console.log(x[1].substr(1)); // Error, 'number' does not have 'substr'
?????????
当访问一个越界的元素,会使用联合类型替代:
x[3] = 'world'; // OK, 字符串可以赋值给(string|number)类型
但是我在编辑器里使用的时候是报错的,Index '2' is out-of-bounds in tuple of length 2,我也不知道为什么??
5. 枚举
enum
类型是对JavaScript
标准数据类型的一个补充。使用枚举类型可以为一组数值赋予友好的名字。
enum Color {Red, Green, Blue}
let c: Color = Color.Green;
默认情况下,从0开始为元素编号。你也可以手动的指定成员的编号。例如,我们将上面的栗子改成从1开始编号:
enum Color {Red = 1, Green, Blue}
let c: Color = Color.Green;
或者采用全部手动赋值:
enum Color {Red = 1,Geeen = 2, Blue = 4}
let c: Color = Color.Green
编译后的js
var Color;
(function (Color) {
Color[Color["Red"] = 1] = "Red";
Color[Color["Green"] = 2] = "Green";
Color[Color["Blue"] = 4] = "Blue";
})(Color || (Color = {}));
var c = Color.Green;
所有的表达式都有返回值,它的返回值就是等号右边的赋值。
枚举类型提供的一个遍历是你可以由枚举的值得到它的名字。
例如,我们知道数值为2,但是不确定它映射到Color里的哪个名字,我们可以查找相应的名字:
enum Color {Red = 1, Green, Blue}
let colorName: string = Color[2];
console.log(colorName); // 显示'Green'因为上面代码里它的值是2
这个试了一下不给数值number,发现没办法通过这个取值
enum Color {Red = 'r', Green = 'g', Blue = 'b'}
let c: Color = Color.Green;
console.log(c) // g
let colorName:string = Color[2]
console.log(colorName) // undefined
我们看一下编译后的javascript
代码就明白了:
var Color;
(function (Color) {
Color["Red"] = "r";
Color["Green"] = "g";
Color["Blue"] = "b";
})(Color || (Color = {}));
var c = Color.Green;
console.log(c);
var colorName = Color[2];
console.log(colorName);
6. 特殊类型
6.1 any
any
类型在 TypeScript
类型系统中占有特殊的地位。它提供给你一个类型系统的【后门】,TypeScript
将会把类型检查关闭。在类型系统里any
能够兼容所有的类型(包括它自己)。因此,所有的类型都能够被赋值给它。它也能被赋值给其他任何类型。
let power: any;
//赋值任意类型
power = '123'
power = 123
let num:number;
num = power;
power = num;
6.2 null 和 undefined
在类型系统中,JavaScript 中的 null 和 undefined 字面量和其他被标注了 any 类型的变量一样,都能被赋值给任意类型的变量,如下例子所示:
let num: numer;
let str: string;
// 这些类型能被赋予
num = null;
str = undefined;
6.3 void
使用 :void
来表示一个函数没有一个返回值
function log(message:string):void{
console.log(message)
}
声明一个void
类型的变量没有什么大用,因为你只能为它赋予undefined
和null
:
let unusable:void = undefined
7.泛型
软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。
不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。
举一个简单的演变例子:
当不实用泛型的时候,你的代码可能是像这样:
function identity(arg:number):number{
return arg;
}
这个函数可以接收number
类型,返回的也是number
类型,考虑到这个函数的可重用性,或者,我们可以使用any
类型来定义函数像这样:
function identity(arg:any):any{
return arg;
}
使用any
类型会导致这个函数可以接受任何类型的arg
参数,且任何类型的值都可能被返回。
我们需要一种方法使返回值的类型与传入参数的类型是相同的。
接下来我们可以把代码像下面这样:
function identity<T>(arg:T):T{
return arg
}
我们给 identity
添加了类型变量 T
。 如果传入的类型(比如:number
),我们就可以知道返回的类型也是number
。现在我们就可以知道参数类型与返回值类型是相同的了。这有助于我们跟踪函数里使用的类型的信息。
我们把这个版本的identity
函数叫做 泛型。 它可以使用与多个类型,不同于使用any
,的不确定性,还能保持像第一个例子一样的准确性,参数类型
与返回值类型
是相同
的。
7.1 泛型的使用
我们定义了泛型函数之火,可以使用两种方法使用。
第一种是传入所有的参数,包含类型参数:
let output = identity<string>('myString');//type of output will be 'string'
这里我们明确的指定了T
是string
类型,并做为一个参数传给函数,并且确定output
的类型是string
.
注意⚠️:使用<>
不是()
第二种方法,利用类型推论--即编译器会根据传入的参数自动的帮助我们确定T
的类型。
let output = identity("myString");// type of output will be 'string'
这里并没有使用(<>
)来明确地传入类型;编译器可以查看myString
的值,然后把T
设置为它的类型。
7.2 使用泛型变量
使用泛型创建像identity
这样的泛型函数时,编译器要求你在函数体必须正确的使用这个通用的类型。换句话说,你必须把这些参数当作时任意或所有类型。
看下我们之前写的泛型例子:
function identity<T>(arg:T):T{
return arg
}
当我们试图在函数内输出arg.length
的时候,编译器就会报错类型“T”上不存在属性“length”
function idenfity<T>(arg:T):T{
console.log(arg.length) // Error: T doesn't have .length
return arg
}
注意⚠️:
类型变量T
代表的时任意类型,所以使用这个函数的人可能传入的是个数字,而数字时没有.length
属性的。
然后我们假设想操作T
类型的数组而不直接是T
,由于我们操作的是数组,此时.length
的属性应该是存在。
代码像这样:
function loggingIdentity<T>(arg: T[]):T[]{
console.log(arg.length) // Array has a .length,so no more error
return arg
}
我们可以这样理解loggingIdentity
的类型:泛型函数loggingIdentity
,接收类型参数T
和参数arg
,它是个元素类型是T
的数组,并返回元素类型T
的数组。如果我们传入数字数组,将返回一个数字数组,因为此时T
的类型为number
。这可以让我们把泛型变量T
当作类型的一部分使用,而不是整个类型,增加了灵活性。
我们还可以这样实现上面的例子:
function loggingIdentity<T>(arg:Array<T>):Array<T>{
console.log(arg.length)
return arg
}
在计算机科学中,许多算法和数据结构并不会依赖于对象的实际类型。然而,你仍然会想在每个变量里强制提供约束。
例如:在一个函数中,它接受一个列表,并且返回这个列表的反向排序,这里的约束是指传入至函数的参数与函数的返回值:
function reverse<T>(items:T[]):T[]{
const toreturn = []
for(let i = items.length - 1;i>=0;i--){
toreturn.push(items[i])
}
return toreturn
}
const sample = [1,2,3]
let reversed = reverse(sample)
console.log(reversed)
reversed[0] = '1'; // Error
reversed = ['1', '2']; // Error
reversed[0] = 1; // ok
reversed = [1, 2]; // ok
这个栗子中,函数reverse
接受一个类型为T
的数组items:T[]
,返回值为类型T
的一个数组(注意:T[]
),函数 reverse
的返回值类型与它接受的参数类型一样。当你传入var sample = [1, 2, 3]
时,TypeScript
能推断出 reverse
为number[]
类型,从而能给你类型安全。于此相似,当你传递一个string[]类型的数组时,TypeScript
能推断出为string[]
类型,
如:
const strArr = ['1','2']
let reversedStrs = reverse(strArr)
reversedStrs = [1, 2]; // Error
如果你的数组是const sample = [1,false,3]
等同于const sample: (number | boolean)[]
,所以下面的代码也能可以的,如果是数组里有两种甚至三种类型的时候,它是能够推断出(number | boolean)
这种或的类型的。也就是下面所说的联合类型。
function reverse<T>(items:T[]):T[]{
const toreturn = []
for(let i = items.length - 1;i>=0;i--){
toreturn.push(items[i])
}
return toreturn
}
const sample = [1,false,3]
let reversed = reverse(sample)
console.log(reversed)
reversed[0] = true; // OK
reversed = [3, true]; // OK
reversed[0] = 1; // ok
reversed = [1, 2]; // ok
8.联合类型
联合类型表示取值可以为多种类型中的一种。
8.1简单的例子
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven'
myFavoriteNumber = 7
let myFavoriteNumber: string | number;
myFavoriteNumber = true;
// index.ts(2,1): error TS2322: Type 'boolean' is not assignable to type 'string | number'.
// Type 'boolean' is not assignable to type 'number'
联合类型使用|
分隔每个类型。
这里的let myFavoriteNumber: string | number;
的含义是,允许myFavoriteNumber
的类型是string
或者number
,但是不能是其他类型。
8.2 访问联合类型的属性或方法
当TypeScript
不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型里的共有的属性或方法。
function getLength(something:string|number):number{
return something.length
}
// Error 类型“string | number”上不存在属性“length”。
类型“number”上不存在属性“length”。
上例中,length
不是string
和number
的共有属性,所以会报错。
访问string
和number
的共有属性是没问题的:
function getLength(something:string|number):string{
return something.toString()
}
联合类型的变量在被赋值的时候,会根据类型推论的规则推断出一个类型:
let myFavoriteNumber:string|number;
myFavoriteNumber = 'seven';
console.log(myFavoriteNumber.length)
myFavoriteNumber = 7
console.log(myFavoriteNumber.length) // Rrror 类型“number”上不存在属性“length”。
上例中,第二行的myFavoriteNumber
被推断成了string
,访问它的length
属性不会报错。而第四行的myFavoriteNumber
被推断成了number
,访问它的length
属性时就报错了。
一个常见的用例是一个可以接受单个对象或者对象数组的函数:
function formatCommandline(command: string[] | string) {
let line = '';
if (typeof command === 'string') {
line = command.trim();
} else {
line = command.join(' ').trim();
}
// Do stuff with line: string
}
2.TypeScript 基础入门(二)的更多相关文章
- Swift语法基础入门二(数组, 字典, 字符串)
Swift语法基础入门二(数组, 字典, 字符串) 数组(有序数据的集) *格式 : [] / Int / Array() let 不可变数组 var 可变数组 注意: 不需要改变集合的时候创建不可变 ...
- C#基础入门 二
C#基础入门 二 循环语句 与C语言中用法相同. continue:结束本次循环(continue)后面的代码不再执行,进入下次循环(通常与if连用). 数组 一维数组定义:int[] intArra ...
- TypeScript 基础入门(一)
1.TypeScript是什么? TypeScript 是 JavaScript 的一个超集,TypeScript 在 JavaScript 的基础上添加了可选的 静态类型 和基于 类 的面向对象编程 ...
- JAVA之Mybatis基础入门二 -- 新增、更新、删除
上一节说了Mybatis的框架搭建和简单查询,这次我们来说一说用Mybatis进行基本的增删改操作: 一. 插入一条数据 1.首先编写USER.XML(表的xml)使用insert元素,元素写在map ...
- C#学习笔记---基础入门(二)
枚举 枚举是被命名的整型常数的集合:枚举类型的变量只有赋值后才能使用:不同枚举中的枚举值可以重名:可以自定义枚举值. enum Playstates { 跑, 跳,下滑,左转,右 ...
- Linux 基础入门二
1.远程连接 ssh协议:secure shell ~]# ss -tnl 查看系统是否监听在tcp协议的22号接口: ~]# ip addr list 或者 ifconfig 查看ip地址 确 ...
- Mybatis框架基础入门(二)--架构简介
mybatis配置 SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息. mapper.xml文件即sql映射文件,文件中配置了操作数据库的 ...
- [Spring框架]Spring AOP基础入门总结一.
前言:前面已经有两篇文章讲了Spring IOC/DI 以及 使用xml和注解两种方法开发的案例, 下面就来梳理一下Spring的另一核心AOP. 一, 什么是AOP 在软件业,AOP为Aspect ...
- [Spring框架]Spring AOP基础入门总结二:Spring基于AspectJ的AOP的开发.
前言: 在上一篇中: [Spring框架]Spring AOP基础入门总结一. 中 我们已经知道了一个Spring AOP程序是如何开发的, 在这里呢我们将基于AspectJ来进行AOP 的总结和学习 ...
随机推荐
- CentOS7下Elastic Stack 5.0日志分析系统搭建
原文链接:http://www.2cto.com/net/201612/572296_3.html 在http://localhost:5601下新建索引页面输入“metricbeat-*”,之后ki ...
- 【CF860E】Arkady and a Nobody-men 长链剖分
[CF860E]Arkady and a Nobody-men 题意:给你一棵n个点的有根树.如果b是a的祖先,定义$r(a,b)$为b的子树中深度小于等于a的深度的点的个数(包括a).定义$z(a) ...
- 【BZOJ1814】Ural 1519 Formula 1 插头DP
[BZOJ1814]Ural 1519 Formula 1 题意:一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数.(n,m<=12) 题解:插头DP板子题,刷板 ...
- 遮挡剔除 Occlusion Culling(转)
一.首先介绍下draw call(这个东西越少你的游戏跑的越快): 在游戏中每一个被展示的独立的部分都被放在了一个特别的包中,我们称之为“描绘指令”(draw call),然后这个包传递到3D部分在屏 ...
- tomcat+redis会话共享
1.基础环境: jdk1. tomcat7 redis nginx 2.添加依赖的jar包到tomcat的lib目录(http://pan.baidu.com/s/1eRAwN0Q) 3.配置tomc ...
- CentOS6.5安装配置PPTP
本次安装环境为Ucloud云服务器 1,操作系统版本检查 2,安装ppp,pptp yum install -y ppp rpm -ivh http://static.ucloud.cn/pptpd- ...
- PAT天梯赛L2-004 这是二叉搜索树吗【递归】
L2-004. 这是二叉搜索树吗? 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 一棵二叉搜索树可被递归地定义为具有下列性质的 ...
- octomap的简介
装载自高翔博士的博客:https://www.cnblogs.com/gaoxiang12/p/5041142.html 什么是octomap? RGBD SLAM的目的有两个:估计机器人的轨迹,并建 ...
- Python装饰函数
from time import ctime, sleep def tsfunc(func): def wrappedFunc(): print('[%s] %s() classed' % (ctim ...
- 51nod 1009 - 数字1的数量 - [数位DP][模板的应用以及解释]
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1009 基准时间限制:1 秒 空间限制:131072 KB 给 ...