三、函数
TypeScript中函数的格式:
let myAdd: (baseValue: number, increment: number) => number =
function(x: number, y: number): number { return x + y; };
-
标准格式
//格式1 function(x: number, y: number): number { return x + y; }; //格式2 let myAdd: (x: number, y: number) => number = function(x: number, y: number): number { return x + y; };
- 类型推断(左边根据右边表达式推断类型,简化书写)
标准格式书写的太过麻烦,TypeScript有类型推断机制,可以简化写法。
推断过程:入参x,y都是number,它们相加是number类型,返回值可以推断出来可省
//类型推断(简化写法) //格式1 function(x: number, y: number){ return x + y; }; //格式2 let myAdd = function(x: number, y: number) { return x + y; };
- 类型推断(左边根据右边表达式推断类型,简化书写)
-
默认参数和剩余参数
//默认参数 不是必须放在最后,但是放在前面调用时必须显示传入undefined function myAdd(name:string,sex:string='男'){ console.log(`name:${name},sex:${sex}`) }
四、泛型
软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。
-
定义泛型
(1)泛型函数//如何定义一个泛型函数 function test<T>( a:T ):T{//代表函数test 入参类型是T 返回值类型也是T return T ; } //这种泛型函数如何使用?? //方法一:传入所有的参数,包含类型参数 var value = test<String>("this is a test"); //方法二:使用类型推断的机制,通过入参的类型推断出泛型的类型和返回值的类型 var value = test("this is a test");
(2)泛型类型
//上面的泛型函数,如何“精确”的赋值给普通变量呢??也就是如果变量定义该如何表示它的类型 var myTest: <T>(arg: T) => T = test;//这样就一目了然了,像函数声明一样 var myTest: <U>(arg: U) => U = test;//换个泛型参数名称也可以 var myTest: {<T>(arg: T): T} = test;//使用带有调用签名的对象字面量定义泛型函数 //使用泛型接口 interface GenerTestFn{ <T>(arg: T): T; } var myTest: GenerTestFn= test;
(3)泛型类
// 如果需要构建一个复杂的对象,希望可以通用的话,可以使用泛型类的方式解决 lass GenericNumber<T> { zeroValue: T; add: (x: T, y: T) => T; } let myGenericNumber = new GenericNumber<number>(); myGenericNumber.zeroValue = 0; myGenericNumber.add = function(x, y) { return x + y; }; //注意:类有两部分:静态部分和实例部分。 //泛型类指的是实例部分的类型,所以类的静态属性不能使用这个泛型类型。
-
泛型的约束
//在这段代码里会报 泛型T没有.lenth属性
//之所以这样是因为,T可以是任意类型,不能保证一定有 length这个属性
function loggingIdentity<T>(arg: T): T {
console.log(arg.length); // 错误 该对象没有.lenth属性
return arg;
}
//解决方案
//使用接口来描述泛型的约束条件,缩小泛型的范围,确保传入的对象一定有 .length这个属性
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // 对象一定有 .length这个属性 不抱错
return arg;
}
(1)在泛型约束中使用类型参数
//你可以声明一个类型参数,且它被另一个类型参数所约束。
//现在我们想要用属性名从对象里获取这个属性。 并且我们想要确保这个属性存在于对象 obj上,因此我们需要在这两个类型之间使用约束
function getProperty(obj: T, key: K) {
return obj[key];
}
let x = { a: 1, b: 2, c: 3, d: 4 };
getProperty(x, "a"); // x 中有 "a"
getProperty(x, "m"); // 错误,x中没有m属性
(2)在泛型里使用类类型
//在TypeScript使用泛型创建工厂函数时,需要引用构造函数的类类型
function create<T>(c: {new(): T; }): T {
return new c();
}