Typescript 学习笔记
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的发展,也许这并不是一个玩笑。