TypeScript是一种由微软开发的开源 、跨平台的编程语言。它是JavaScript的超集,TypeScript的作者是安德斯·海尔斯伯格,C#的首席架构师。它是开源和跨平台的编程语言,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。TypeScript最终会被编译为JavaScript代码。TypeScript添加了可选的静态类型系统、很多尚未正式发布的ECMAScript新特性(如装饰器 )。2012年10月,微软发布了首个公开版本的TypeScript,2013年6月19日,在经历了一个预览版之后微软正式发布了正式版TypeScript。当前最新版本为TypeScript4.0。TypeScript扩展了JavaScript的语法,所以任何现有的JavaScript程序可以运行在TypeScript环境中。TypeScript 起源于使用JavaScript开发的大型项目 。由于JavaScript语言本身的局限性,难以胜任和维护大型项目开发。因此微软开发了TypeScript ,使得其能够胜任开发大型项目。由于TypeScript起源于JavaScript,使得TypeScript既具备函数式编程特性又具备面向对象编程的特性。在工作中常会使用React做前端页面开发,React是支持TypeScript和ES6的,社区文档和官方资料基本都是基于TypeScript,因此学习记录一下TypeScript的心得笔记
接口
接口的作用:在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范,在程序设计里面,接口起到一种限制和规范的作用。接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据,也不关心这些类里方法的实现细节,它只规定这批类里必须提供某些方法,提供这些方法的类就可以满足实际需要。 typescrip中增加了更灵活的接口类型,包括属性、函数、可索引和类等。
属性接口
interface FullName{
firstName:string; //注意;结束
secondName:string;
}
function printName(name:FullName){
// 必须传入对象 firstName secondName
console.log(name.firstName+'--'+name.secondName);
}
// printName('1213'); //错误
var obj={ /*传入的参数必须包含 firstName secondName*/
firstName:'张',
secondName:'三'
};
printName(obj)
可选接口
interface FullName{
firstName:string;
secondName?:string; // 属性可选(可传可不传)
}
function getName(name:FullName){
console.log(name)
}
getName({
firstName:'firstName'
})
函数类型接口:对方法传入的参数 以及返回值进行约束
// 加密的函数类型接口
interface encrypt{
(key:string,value:string):string;
}
var md5:encrypt=function(key:string,value:string):string{
//模拟操作
return key+value;
}
console.log(md5('name','zhangsan'));
可索引接口: 数组、对象的约束(不常用)
- 可索引接口对数组约束
interface UserArr{
[index:number]:string // 数组索引为number类型,值为string类型
}
var arr:UserArr=['aaa','bbb'];
// var arr:UserArr=[123,'bbb']; /*错误*/
- 可索引接口对对象约束
interface UserObj{
[index:string]:string // 对象key为string类型,value为string类型
}
var arr:UserObj={name:'张三'};
类类型接口:对类的约束和抽象类抽象有点相似
interface Animal{
name:string;
eat(str:string):void;
}
class Dog implements Animal{
name:string;
constructor(name:string){
this.name=name;
}
eat(){ // 参数可选,但必须实现eat方法
console.log(this.name+'吃粮食')
}
}
var d=new Dog('小黑');
d.eat();
接口扩展:接口可以继承接口
interface Animal{
eat():void;
}
interface Person extends Animal{
work():void;
}
class Web implements Person{
public name:string;
constructor(name:string){
this.name=name;
}
// 实例必须实现父类指定方法
eat(){
console.log(this.name+'喜欢吃馒头')
}
work(){
console.log(this.name+'写代码');
}
}
var w=new Web('小李');
w.eat();
方法
方法定义
TypeScript定义函数的几种方式
函数声明法
function add(n1: number, n2: number): number { return n1 + n2; }; console.log(add(1, 2)); //3
函数表达式法
var add = function (n1: number, n2: number): number { return n1 + n2; }; console.log(add(1, 2)); //3
箭头函数
var add = (n1: number, n2: number): number => { return n1 + n2; } console.log(add(1, 2)); //3
函数类型接口
接口能够描述JavaScript中对象拥有的各种各样的外形。 除了描述带有属性的普通对象外,接口也可以描述函数类型。为了使用接口表示函数类型,我们需要给接口定义一个调用签名。 它就像是一个只有参数列表和返回值类型的函数定义。参数列表里的每个参数都需要名字和类型。如下示例
interface SomeInterface { (arg1: string, arg2: string): boolean; } // 实现接口函数 let someFunc: SomeInterface someFunc = function (arg1: string, arg2: string) { const res = arg1.search(arg2) return res > -1; } console.log(someFunc('weast','east'));
方法参数
对于一些功能比较复杂的函数,需要将很多配置项作为参数传入,这时候传统的位置参数表就不太方便了,因为对于配置项参数,我们往往会设置默认值,希望使用者无需按顺序传入所有参数,而只要指明哪几个参数需要特别配置。比如一个简单的字符串格式化函数,除了必需的传入值 value
外,有三个配置项分别是,indent
:缩进;caseMode
:大小写;callback
:转换完成后的回调的方法,一般我们的代码会这么写
function transform(value, indent, caseMode, callback) {
// ... do something
}
那么使用者就必须记住所有配置参数的位置,要是只想设置 caseMode
,需要写成如下尴尬的形式:
transform('someStr', caseMode: 'upper');
现在配合上 ES6 的解构赋值和函数默认值,直观性和默认值可以解决了
function transform(value, {
indent = 2,
caseMode = 'upper',
callback,
} = {}) {
// ... do something
}
不过约束性还是不够,不能实现“必选参数”、“可选参数”的功能,这时候就要 TypeScript 上场了。
使用TypeScript 设置参数类型,默认值
function transform(value: string, {
indent = 2,
caseMode = 'upper',
callback,
}:{
indent?: number,
caseMode?: string,
callback?: (rst: string) => void,
} = {}) {
// ... do something
}
除了类型检查外,TypeScript 可以对必选参数进行空值检查。然后再通过?:
手动设置可选参数(这是继承了c#语言的特性),在以上的定义中,“命名参数” 用上了 {}: {}={}
的结构进行定义,格式上要分成两段,另外由于本质上是个对象参数,外面还是不能忘了大括号的,写法略有些冗长,但是 TypeScript 的团队 表示 由于保留位置限制、表达式解析等种种原因,目前不会加入真正的“命名参数”特性,因此目前只能这样写。
由于TypeScript同时也支持函数式编程,所以语法糖上就与Java有很大的区别
声明入参是函数的函数
// 声明multipleCallbacks函数
// 入参类型 接收一个firstCallback函数,函数入参s为string类型,返回类型为void类型
// 接收一个secondCallback函数,函数入参b为boolean类型,返回类型为boolean类型
//返回类型 返回类型为void
multipleCallbacks(firstCallback: (s: string) => void, secondCallback: (b: boolean) => boolean): void {
firstCallback("hello world")
let result: boolean = secondCallback(true)
console.log("Resulting boolean: " + result)
}
对于一个函数要声明多个入参,且入参也是多个函数,可以使用TypeScript约束,入参函数的参数类型和返回值类型
方法泛型
在软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。因此TypeScript也和许多后端语言如Java一样支持泛型,对于习惯了Java语言的人来说,泛型的作用不言而喻。泛型的出现使得JavaScript也具备了灵活的代码抽象能力。
方法泛型
普通参数
// 入参 value1 string类型 // 返回值 string类型 function getData(value1:string):string{ console.log(value1); return value1; }
使用泛型
// T表示泛型,具体什么类型是调用这个方法的时候决定的 function getData<T>(value:T):T{ return value; } // 调用例子 getData<number>(123); getData<string>('1214231');