学习笔记

Typescript 学习笔记

#Typescript学习笔记 #编程语言对比 #javascript #从问题出发的学习法 #泛型

Typescript的诞生

在我用 JavaScript(Js) 写代码的时候,会觉得非常流畅,不用去定义变量的类型,自由度很高,还可以隐式转换,例如

let a = '1' + 0
console.log(a) 
# 打印字符串 10

然而,所谓成也萧何,败也萧何,在中大型项目中,这样的自由度常常会带来很大的麻烦,在代码过多时,程序员就很难记得变量的类型,或者数字写成了字符串,但是Js只会在编译的时候报错。为了解决这个问题,微软开发了Typescript(Ts)语言。

什么是Ts语言?教程上说Ts是Js的一个超集,嗯,我觉得可以这么理解,Ts是在Js的基础上给Js带上了一个“枷锁”,也就是类型声明的”枷锁“。

为了保证代码的可维护性,Ts牺牲了自由度。为了尽可能不让这个解决方法也成为‘萧何’—虽然提高了自由度,但代码过于繁琐,Ts里面有了一些简化代码的规则,例如接口,泛型;而这些简化的规则也成为了学习的难点。人生也是这样,解决问题,产生问题,不断的取舍,小小的感慨一下。

言归正传,我们今天的内容是学习Typescript的基本语法。

Typescript 的基本类型

何为基本类型,就是js中有的,基本语法是在变量后面加:type来声明变量

1. 数字,字符串,布尔类型


let a:number = 1                    
let b:string = 'hello'             
let c:boolean = true

2. 数组,元组类型


let d:number[] = [1,2,3]
let e:string[] = ['a','b','c']
let f:(number|string)[] = [1,'a',2]  #(Type1|Type2)这种类型叫做联合类型,即既可以为Type1或Type2

#元组--有固定元素的数组
let g:[number,number] = 【1,2】
let

3. 函数类型


##3.1 假设有一个求和函数add,如下,

function add(a,b){
	return a + b
	}

##转化成Ts语法如下:function add(a:type,b:type):type(这里是返回值的类型){}

function add(a:number,b:number):number{
	return a + b
}

##返回值为空值

function print(a:string,b:string):void{
	console.log(a+b)
}

##3.2 箭头函数写法1--针对变量的类型

const sum = (a:number,b:number):number =>{
	return a + b
}

#箭头函数写法2--针对函数的类型--类型写到了函数名后面
const productor:(a:number,b:number) =>number = (a,b)=>{
	return a*b
}

##3.3 可选参数--在参数与类型之间加上一个?
function print(a?:string):void { }

4. 对象类型


##--在对象名后类型定义,属性之间用‘;’隔开,本质上还是对上述基本类型的组合

const obj:{a:number;b:string;sayhi(a:number):number} = {
	a:1,
	b:'a',
	sayhi(a){return a}
}

5. 字面量类型&枚举类型


#5.1 字面量类型-本质就是常量

const a:'hello' = 'hello'

#多用于联合声明变量来构造一个伪‘枚举’类型

function Dir(dir:‘up’ | ‘down’ | ‘left’ | ‘right’):void {console.log(dir)}

Dir('up') #打印up

#5.2 枚举类型

enum direciton {up,down,left,right}

function Dir(dir:direction):void {console.log(dir)}

Dir(dir.up) #打印0 类似于下拉框选择器

enum direction {up = ‘up’,down = ‘down’,left = ‘left’,right = ‘right’}

Dir(dir.up) #打印up

6.class 类


##关键字 

### public 外部和内部都可访问
### private 只有类内部可以访问
### protected 只有类内部和子类可以访问,后面会说到子类


class Person {

	public name:string,
	private age:number,
	protected gender:string

	constructor(name:string,age:number){
		this.age = age
		this.name = name
	}

	tellage():void{cosole.log(this.age)} ##外部和子类均不可调用该private数据
	
	sayhi():void{console.log('hello')}
}


const person = new Person()

Typescript的简化操作

好了,上面谈到了Js的基本类型的定义语法,大致来讲就是—:type 这么一个格式。但是尽管定义起来比较简单,但是架不住定义的变量多啊,尤其是对象的类型,每次都写这么一次,那会大大降低开发的效率,所以,TYpescript给出了以下的方法。

1. 如果Typescript知道你的类型,则不用定义类型。---类型推论


let a = 18   <=>  let a:number = 18         #初始化赋值不需要加类型

function(a:number){return a} <=> function(a:number):number{return number} #函数返回值可以确定的不用加

2. 如果想重复使用一个类型结构

如果一个数组,对象或者类的结构比较复杂,那再次定义一个对象的时候,为了免重复造轮子,Ts语言给出了以下的方法

2.1自定义type
type customerType = (number|string)[]
let f:customerType = [1,'a',2]
2.2 接口interface
#2.2 接口interface,仅用于对象

interface customerObjType{
	a:number;
	b:string;
	sayhi(x:number):number
}

let obj:customerObjType = {
	a:1,
	b:'a'
	sayhi(x:number){return x}
}

2.3 扩展

扩展,故名思义,是在原有类型的基础上的扩展。

##1 接口的扩展extends

interface customerObjType{...}

interface customerObjType2 = customerObjType extends customerObjType { c:number[]}
#等价于
interface customerObjType2{
	...    #customerObjType原有的属性
	c:number[];
}

##2.类的扩展 

## extends<针对类>

class Person{}

class Doctor extends Person {career:'doctor'}

## implements<针对接口>

interface Career{career:string}

class Doctor implements Career{career:'doctor'}

##3. 交叉类型

interface Dog {...}
interface Cat{...}
type Pet = Dog & Cat  #Pet里面,dog和cat共同的属性合并,不同的属性都添加,就是一个并集

4.Typeof

let t :{a:number;b:string} = {a:1,b:'a'}

let t1:typeof(t) = {a:2,b:'hello'}

Typescript面对不确定性怎么办

在我编程的时候,有的时候并不确定变量的类型是什么?只有在我使用的时候,才知道是什么,这个时候应该怎么半呢?没有关系,泛型来帮助你解决。一般用于接口,函数,类中。

语法是<自定义名称>

#type类似于是储存类型的一个量,在使用时可由类型推论来自动判断

function person <type> (name:type):type {return name} 

person<string>('zhangshan') <=> person('zhangshan')

1.泛型添加约束—确保更准确

##给type添加一个length属性,如果没有参数length属性则报错

interface ILength {length: number}

function id<Type extends ILength>(value: Type): number{
	return value.length
}


## extends keyof type 这里是type中的任意一个属性
function getProp<Type, Key extends keyof Type>(obj: Type, key: Key) {
return obj[key]

}

2. 泛型接口和泛型类

那自然而然我们就会把这个工具迁移到其他的类型上,记住泛型的符号是<>

interface IdFunc<Type> {
	id: (value: Type) => Type
	ids: () => Type[]
}

class GenericNumber<NumType> {
	defaultValue: NumType
	add: (x: NumType, y: NumType) => NumType
}

3. 泛型工具

#Type 是一个类型,例如接口,keys是Type的某些属性
Partial<Type>   #将所有属性设置为可选属性
Readonly<Type>。 #将所有属性设置为只读
Pick<Type,keys> #从Type属性中抽出keys属性作为新的类型
Record<keys,Type> #以keys作为属性名,type作为属性类型来构造新的属性类型

总结

写到这里,没想到花了这么长时间,这让我想到另一件事情,ts为了解决js的问题,加上了类型声明,为了保证开发效率又增加了很多工具,例如接口,泛型,type,extends;这又提高了复杂度,在js的基础上学完ts可能只需要一天,但用好ts并不是一件容易的事情。

这就又背弃了js的开发初衷。是谓天道有轮回啊,未来的螺旋手里剑会不会又回来呢?看如今ai的发展,也许这并不是一个玩笑。