函数声明
为函数定义类型
function hi(name:string): void {
console.log(`hi ${name}`)
}
可选参数、默认参数、类型推断、剩余参数
function hi(name: string, age?:number):void {} // 可选参数 age
function hi(name: string, age = 18): void{} // age 默认参数18 推断age的类型为number
function hi(name:string, age:number = 19): string | number{} // 可以给默认参数类型。 返回string或者number
function buildName(firstName: string, ...restOfName: string[]) { // 剩余参数
return firstName + " " + restOfName.join(" ");
}
let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
泛型
function identity(arg: any): any { // 我们可以传入number而返回string
return arg;
}
我们需要一种方法使返回值的类型与传入参数的类型是相同的
这里,我们使用了 类型变量,它是一种特殊的变量,只用于表示类型而不是值。
function identity<T>(arg: T): T { // T帮助我们捕获用户传入的类型
return arg;
}
我们定义了泛型函数后,可以用两种方法使用。 第一种是,传入所有的参数,包含类型参数:
let output = identity<string>("myString"); // type of output will be 'string'
第二种方法更普遍。利用了类型推论 -- 即编译器会根据传入的参数自动地帮助我们确定T的类型:
let output = identity("myString"); // type of output will be 'string'
会出现如下的报错, 我们使用了arg的.length属性,但是没有地方指明arg具有这个属性。 (泛型约束会提及)
function loggingIdentity<T>(arg: T): T {
console.log(arg.length); // Error: T doesn't have .length
return arg;
}
我们可以这样(泛型约束会提及)
function loggingIdentity<T>(arg: T[]): T[] {
console.log(arg.length); // Array has a .length, so no more error
return arg;
}
泛型接口
interface GenericIdentityFn {
<T>(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn = identity;
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;
泛型类
class 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; };
泛型约束
我们想访问arg的length属性,但是编译器并不能证明每种类型都有length属性,所以就报错了。
创建一个包含 .length属性的接口,使用这个接口和extends关键字来实现约束:
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // Now we know it has a .length property, so no more error
return arg;
}
现在这个泛型函数被定义了约束,因此它不再是适用于任意类型:
loggingIdentity(3); // Error, number doesn't have a .length property
我们需要传入符合约束类型的值,必须包含必须的属性:
loggingIdentity({length: 10, value: 3});
重载
function add(a: number, b:number):number;
function add(a: string, b:string):string;
function add(a: any, b: any): any {
return a + b
}
类型兼容
interface Named {
name: string;
}
let x: Named;
let y = { name: 'Alice', location: 'Seattle' };
x = y;
Unsound 不完备的。有瑕疵的。
enum EventType { Mouse, Keyboard }
interface Event { timestamp: number; }
interface MouseEvent extends Event { x: number; y: number }
interface KeyEvent extends Event { keyCode: number }
function listenEvent(eventType: EventType, handler: (n: Event) => void) {
/* ... */
}
// Unsound, but useful and common
listenEvent(EventType.Mouse, (e: MouseEvent) => console.log(e.x + ',' + e.y)); // 有瑕疵的,但是不会报错。mouseEvent是Event的子类型
// Undesirable alternatives in presence of soundness
listenEvent(EventType.Mouse, (e: Event) => console.log((<MouseEvent>e).x + ',' + (<MouseEvent>e).y)); // 使用了类型断言
listenEvent(EventType.Mouse, <(e: Event) => void>((e: MouseEvent) => console.log(e.x + ',' + e.y))); // 这个看不懂
listenEvent(EventType.Mouse, (e: number) => console.log(e)); // 完全不一致所以会报错
```