TypeScript基础笔记(小满版本)(三)

简介: TypeScript基础笔记(小满版本)(三)

生成器(Builder)


又称建造者模式,该模式是一种创建型设计模式,能够分步骤创建复杂对象。该模式允许使用相同的创建代码生成不同类型和形式的对象。


具体内容请跳转链接查看:设计模式-生成器


for…of 语句


for…of 会遍历可迭代的对象,调用对象上的 Symbol.iterator方法。(此对象非彼对象,这个对象是指你即将下手的目标)


对象也是不支持的,因为对象没用Symbol.iterator方法。


type mapKeys = string|number//相当于起别名,在下方使用的时候集合了string与number就会相对方便不少
let set:Set<number> = new Set([1,2,3])
let map:Map<mapKeys,mapKeys> = new Map()//这里断言两个mapKeys,一个对应key,一个对应value
map.set('1','小满')
map.set('2','看看腿')
for (let item of set){
    console.log(item)
}//打印出1 2 3
for (let item of arr){
    console.log(item)
}//打印出4 5 6
for (let item of map){
    console.log(item)
}//打印出['1','小满']  ['2','看看腿']
//其实这就是一个语法糖,将of后面的内容遍历存储到of前面的变量中


跟for in 的区别


for in循环出来的是索引而不是内容,这个应该是最本质的区别了


因为for of会调用底层interator里面那个list的.value


泛型(generic) => (TS -- 14上)


泛型简单来说就是类型变量,在 ts 中存在类型,如 number、string、boolean等。泛型就是使用一个类型变量来表示一种类型,类型值通常是在使用的时候才会设置。泛型的使用场景非常多,可以在函数、类、interface 接口中使用


TypeScript中不建议使用 any 类型,不能保证类型安全,调试时缺乏完整的信息。


TypeScript 可以使用泛型来创建可重用的组件。支持当前数据类型,同时也能支持未来的数据类型。扩展灵活,可以在编译时发现类型错误,从而保证了类型安全。


无泛型用法


//数字类型
function num(A:number,B:number):Array<number>{//Array<number>为希望返回number类型的数组
    return [a,b]
}
num(6,9)
//字符串类型
function str(A:string,B:string):Array<string>{//Array<number>为希望返回number类型的数组
    return [a,b]
}
str('小满','穿女装')

一个笨的方法就像上面那样,也就是说 JS 提供多少种类型,就需要复制多少份代码,然后改下类型签名。这对程序员来说是致命的。这种复制粘贴增加了出错的概率,使得代码难以维护,牵一发而动全身。并且将来 JS 新增新的类型,你仍然需要修改代码,也就是说你的代码对修改开放,这样不好。


如果你使用 any 的话,怎么写都是 ok 的, 这就丧失了类型检查的效果。实际上我知道我传给你的是 string,返回来的也一定是 string,而 string 上没有 toFixed 方法,因此需要报错才是我想要的。也就是说我真正想要的效果是:当我用到id的时候,你根据我传给你的类型进行推导。比如我传入的是 string,但是使用了 number 上的方法,你就应该报错。


使用泛型优化


为了解决上面的这些问题,我们使用泛型对上面的代码进行重构。和我们的定义不同,这里用了一个 类型 T,这个 T 是一个抽象类型,只有在调用的时候才确定它的值,这就不用我们复制粘贴无数份代码了。


其中 T 代表 Type,在定义泛型时通常用作第一个类型变量名称。但实际上 T 可以用任何有效名称代替。除了 T 之外,以下是常见泛型变量代表的意思:


  • K(Key):表示对象中的键类型;
  • V(Value):表示对象中的值类型;
  • E(Element):表示元素类型。


function add<T>(a:T,b:T):Array<T>{//通常定义的时候类型是不明确的,所以一般使用T来定义
  return [a,b];
}
add<number>(1,2)//1对应a,2对应b、返回的都是number类型
add<string>('1','2')//这个时候,我们只需要改动这个string,传递到上面的时候就会自动推断为string类型了
//甚至我们可以简写
add(1,2)
add('1','2')//编辑器会自动推断类型,但最好还是写一下,如果你知道你具体需要的是什么的话
//对泛型进行总结就是:定义前不明确类型,使用的时候再明确类型,能够给我们保留有足够的自由度,又不会像any丧失类型检查的效果
我们也可以使用不同的泛型参数名,只要在数量上和使用方式上能对应上就可以。
function Sub<T,U>(a:T,b:U):Array<T|U> {//这个T跟U随便起名字都行,没有强制规范
    const params:Array<T|U> = [a,b]
    return params
}
Sub<Boolean,number>(false,1)//我们这里就将其定义为布尔值类型跟数字类型


定义泛型接口


声明接口的时候 在名字后面加一个 <参数>


使用的时候传递类型


interface MyInter<T> {
   (arg: T): T
}
function fn<T>(arg: T): T {
   return arg
}
let result: MyInter<number> = fn
result(123)


对象字面量泛型


let foo: { <T>(arg: T): T }
foo = function <T>(arg:T):T {
   return arg
}
foo(123)


泛型约束(函数类)


我们期望在一个泛型的变量上面,获取其 length 参数,但是,有的数据类型是没有 length 属性的


function getLegnth<T>(arg:T) {
  return arg.length
}
• 这个时候,我们就可以对其进行约束
interface Len{
    length:number
}
function getLegnth<T extends Len>(arg:T) {//使用接口让泛型T继承了Len
  return arg.length
}
getLength(1)//这个时候我们这样使用就会提示我们类型"number"的参数不能赋给"Len"的参数
//我们依次对数组、字符串、布尔值都进行尝试,分别为可以、可以、不可以

泛型约束|泛型类(TS -- 14下)


使用 keyof 约束对象


其中使用了 TS 泛型和泛型约束。首先定义了 T 类型并使用 extends 关键字继承 object 类型的子类型,然后使用 keyof 操作符获取 T 类型的所有键,它的返回 类型是联合 类型,最后利用 extends 关键字约束 K 类型必须为 keyof T 联合类型的子类型


function prop<T, K extends keyof T>(obj: T, key: K) {
   return obj[key]
}
let o = { a: 1, b: 2, c: 3 }
prop(o, 'a') 
prop(o, 'd') //,我们需要约束一下这个o里面并没有的东西,此时就会报错发现找不到
//通过提示,我门可以看到类型"d"的参数不能赋给类型"a"|"b"|"c"的参数


泛型类


声明方法跟函数类似名称后面定义 <类型>


使用的时候确定类型 new Sub()


//定义泛型的一个类
class Sub<T>{
    attr:T[] = []//这里的:只是普通的:
    add(a:T):T[]{
        return [a]
    }
}
let s = new Sub<number>()//这里已经使用泛型固定为number了
s.attr = [123]//正常运行
s.attr = ['123']//报错
s.add(123)//也是只能传数字
let str = new Sub<string>()//这里已经使用泛型固定为number了
str.attr = [123]//报错
str.attr = ['123']//正常运行
str.add('123')//也是只能传字符串
console.log(s,str)


目录
相关文章
|
9月前
|
JavaScript 前端开发 测试技术
[小笔记]TypeScript/JavaScript数组转置
[小笔记]TypeScript/JavaScript数组转置
90 0
|
9月前
|
JavaScript 前端开发 测试技术
[小笔记]TypeScript/JavaScript模拟Python中的Range函数
[小笔记]TypeScript/JavaScript模拟Python中的Range函数
88 0
|
6月前
|
存储 JavaScript 前端开发
深入浅出TypeScript | 青训营笔记
深入浅出TypeScript | 青训营笔记
46 0
|
8月前
|
JavaScript 前端开发 程序员
typescript入门笔记分享
typescript入门笔记分享
43 0
|
9月前
|
JavaScript 前端开发
TypeScript极速入门笔记1
TypeScript极速入门笔记1
90 4
|
9月前
|
JavaScript 前端开发 Java
小笔记:如何使用代码注释:关于JavaScript与TypeScript 注释和文档的自动生成
小笔记:如何使用代码注释:关于JavaScript与TypeScript 注释和文档的自动生成
669 0
|
9月前
|
JavaScript 前端开发 测试技术
[小笔记]TypeScript/JavaScript模拟Python中的zip(不使用map)
[小笔记]TypeScript/JavaScript模拟Python中的zip(不使用map)
62 0
|
9月前
|
存储 JavaScript 前端开发
TypeScript笔记(15)—— 深入理解TypeScript中的装饰器
TypeScript笔记(15)—— 深入理解TypeScript中的装饰器
104 0
|
9月前
|
存储 JavaScript 前端开发
TypeScript笔记(5)—— 基本数据类型
TypeScript笔记(5)—— 基本数据类型
84 0
|
9月前
|
JavaScript 前端开发 编译器
TypeScript笔记(4)—— TypeScript中的类型注解
TypeScript笔记(4)—— TypeScript中的类型注解
90 0