ts 学习笔记 - 泛型
泛型
泛型(Generics)是指在定义函数、接口或者类的时候, 不预先指定其类型,而是在使用是手动指定其类型的一种特性。
举个栗子
我们需要创建一个函数, 这个函数会返回任何它传入的值。
正常代码如下:
function identity(arg: any): any {
return arg
}
identity(3) // 3
这代代码编译不会出错,但是存在一个显而易见的缺陷, 就是没有办法约束输出的类型与输入的类型保持一致。
这时,我们可以使用泛型来解决这个问题;
function identity<T>(arg: T): T {
return arg
}
identity(3) // 3
上例中,我们在函数名后面加了 <T>
, 其中的 T
表示任意输入的类型, 后面的 T
即表示输出的类型,且与输入保持一致。
当然我们也可以在调用时手动指定输入与输出的类型, 如上述函数指定 string
类型:
identity<number>(3) // 3
泛型约束
在泛型函数内部使用类型变量时, 由于事先并不知道它是那种类型, 所以不能随意操作它的属性和方法:
function loggingIdentity<T>(arg: T): T {
console.log(arg.length) // err
return arg
}
上述函数中 类型 T 上不一定存在 length 属性, 所以编译的时候就报错了。
这时,我们可以的对泛型进行约束,对这个函数传入的值约束必须包含 length
的属性, 这就是泛型约束:
interface lengthwise {
length: number
}
function loggingIdentity<T extends lengthwise>(arg: T): T {
console.log(arg.length) // err
return arg
}
loggingIdentity({a: 1, length: 1}) // 1
loggingIdentity('str') // 3
loggingIdentity(6) // err 传入是参数中未能包含 length 属性
这样我们就可以通过泛型约束的方法对函数传入的参数进行约束限制。
多个参数时也可以在泛型约束中使用类型参数
如你声明了一个类型参数, 它被另一类型参数所约束。现在想要用属性名从对象里湖区这个属性。并且还需确保这个属性存在于这个对象上, 因此需要咋这两个类型之间使用约束,
简单举例来说: 定义一个函数, 接受两个参数 第一个是个对象 obj,第二个个参数是第一参数 key 是对象里面的键名, 需要输入 obj[key]
function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key]
}
let obj = { a: 1, b: 2, c: 3 }
getProperty(obj, 'a') // success
getProperty(obj, 'm') // err obj 中不存在 m 这个参数
泛型接口
interface CreateArrayFunc {
<T>(length: number, value: T): Array<T>
}
let createArr: CreateArrayFunc
createArr = function<T>(length: number, value: T): Array<T> {
let result = T[]: []
for(let i = 0; i < length; i++) {
result[i] = value
}
return result
}
createArray(3, 'x'); // ['x', 'x', 'x']
进一步的, 还可以把泛型参数提前到接口名上:
interface CreateArrayFunc<T> {
(length: number, value: T): Array<T>
}
let createArr: CreateArrayFunc<any>
createArr = function<T>(length: number, value: T): Array<T> {
let result = T[]: []
for(let i = 0; i < length; i++) {
result[i] = value
}
return result
}
createArray(3, 'x'); // ['x', 'x', 'x']
注意: 此时使用泛型接口时, 需要定义泛型的类型
泛型类
与泛型接口类型,泛型也可以定义在类的类型定义中:
class GenericNumber<T> {
zeroValue: T
add: (x: T, y: T) => T
}
let myGenericNumber = new GenericNumber<number>()
myGenericNumber.zeroNumber = 0
myGenericNumber.add = function(x, y) {
return x + y
}
注意: 类有两部分: 静态部分和实例部分。泛型类值的是实例部分的类型,所以类的静态属性不能使用这个泛型类型
泛型参数的默认类型
在 TypeScript 2.3 以后,我们可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推测出时,这个默认类型就会起作用。
function createArr<T = string>(length: number, value: T): Array<T> {
let result: T[] = []
for( let i = 0; i < lenght; i++ ) {
result[i] = value
}
return result
}
ts 学习笔记 - 泛型的更多相关文章
- Java学习笔记--泛型
一个泛型类就是具有一个或者多个类型变量的类. 我们可以只关注泛型,而不会为数据存储的细节而烦恼 . java泛型(一).泛型的基本介绍和使用 http://blog.csdn.net/lonelyro ...
- TS学习之泛型
可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据 不适用泛型的函数 function myfn(args: number): number { return args; } functi ...
- TS学习笔记----(一)基础类型
布尔值: boolean let isDone: boolean = false; 数字: number 和JavaScript一样,TS里的所有数字都是浮点数. 支持十进制和十六进制字面量,TS还支 ...
- ts 学习笔记-基础篇
目录 基础 原始数据类型 布尔值 数字 字符串 空值 Null 和 Undefined 任意值 类型推论 联合类型 接口 数组 函数 类型断言 申明文件 什么是申明文件 三斜线指令 第三方声明文件 内 ...
- Java学习笔记——泛型
假定T不仅要指定接口的类继承.使用下面的方式: public class some<T extends Iterable<T> & Comparable<T>&g ...
- Thinking in Java学习笔记-泛型和类型安全的容器
示例: public class Apple { private static long counter; private final long id = counter++; public long ...
- Java 学习笔记 泛型
泛型 上界匹配 ? extends Number 下界匹配 ? super Number getSimpleName 不包括包名 getName 会包括包名 常和反射联合使用,做框架 Type是一个标 ...
- ts 学习笔记 - 类
目录 类 类的概念 类的用法 属性和方法 类的继承 存取器 静态属性 Typescript 中的用法 抽象类 类的类型 类与接口 类实现接口 接口继承接口 接口继承类 混合类型 类 类的概念 类 (c ...
- ts 学习笔记 - 进阶篇 1
目录 进阶 类型别名 字符串字面量类型 元祖 例子 越界的元素 枚举 手动赋值 常数项和计算所得项 常数枚举 外部枚举 进阶 类型别名 类型别名用来给一个类型起个新名字 type Name = str ...
随机推荐
- Storm之API简介
Storm之API简介 Component组件 1)基本接口 (1)IComponent接口 (2)ISpout接口 (3)IRichSpout接口 (4)IStateSpout接口 (5)IRich ...
- Android基础知识复习之打开照相机拍照并获取照片
对于我来说,做一件事情: 首先要理清我的思路,我要打开照相机,我能想到的是:在Android中我要打开系统应用,肯定需要一个隐式意图,那就要查询Android照相机的源码,查看并找到意图过滤器的书写方 ...
- JAVA项目从运维部署到项目开发(五. Nginx)
<Nginx与Nginx-rtmp-module搭建RTMP视频直播和点播服务器>一文简单介绍了关于直播数据流的nginx相关配置,下面简单介绍下各种项目如何配置nginx. web项目. ...
- Spring applicationContext爆出警告“Resource leak: 'applicationContext' is never closed”
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); 此处applicationCo ...
- Spring Boot2(十五):Shiro记住我rememberMe、验证码Kaptcha
接着上次学习的<Spring Boot2(十二):手摸手教你搭建Shiro安全框架>,实现了Shiro的认证和授权.今天继续在这个基础上学习Shiro实现功能记住我rememberMe,以 ...
- 第一篇博客 安装open live writer
第一篇博客安装open live writer http://openlivewriter.org/ 有的人可能会打不开,所以我准备了一个百度云的链接地址 链接:https://pan.baidu.c ...
- 【iOS】Error: Error Domain=PBErrorDomain Code=7 "Cannot connect to pasteboard server
这几天在用 Swift 开发一个简单的键盘扩展,真机调试时遇到了这个问题,详细信息如下: ***[:] Could not save pasteboard named com.apple.UIKit. ...
- 【有容云案例系列】基于Jenkins和Kubernetes的CI工作流
嘉宾介绍 黄文俊 有容云资深系统架构师 主要负责容器云平台产品架构及设计. 8年工作经验, 有着企业级存储, 云计算解决方案相关理解. 关注于微服务设计思考, 开发流程优化, docker及kuber ...
- Linux内核实战(二)- 操作系统概览
不知道你有没有产生过这些疑问: 桌面上的图标到底是啥?凭啥我在鼠标上一双击,就会出来一些不可描述的画面?都是从哪里跑出来的? 凭什么我在键盘上噼里啪啦地敲,某个位置就会显示我想要的那些字符? 电脑怎么 ...
- Python基础编程 内置函数
内置函数 内置函数(一定记住并且精通) print()屏幕输出 int():pass str():pass bool():pass set(): pass list() 将一个可迭代对象转换成列表 t ...