函数与泛型

函数声明

3.png

为函数定义类型

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(arg: T): T { // T帮助我们捕获用户传入的类型
    return arg;
}

我们定义了泛型函数后,可以用两种方法使用。 第一种是,传入所有的参数,包含类型参数:

let output = identity("myString");  // type of output will be 'string'

第二种方法更普遍。利用了类型推论 -- 即编译器会根据传入的参数自动地帮助我们确定T的类型:

let output = identity("myString");  // type of output will be 'string'

会出现如下的报错, 我们使用了arg的.length属性,但是没有地方指明arg具有这个属性。 (泛型约束会提及

function loggingIdentity(arg: T): T {
    console.log(arg.length);  // Error: T doesn't have .length
    return arg;
}

我们可以这样(泛型约束会提及

function loggingIdentity(arg: T[]): T[] {
    console.log(arg.length);  // Array has a .length, so no more error
    return arg;
}

泛型接口

interface GenericIdentityFn {
    (arg: T): T;
}

function identity(arg: T): T {
    return arg;
}

let myIdentity: GenericIdentityFn = identity;
interface GenericIdentityFn {
    (arg: T): T;
}

function identity(arg: T): T {
    return arg;
}

let myIdentity: GenericIdentityFn = identity;

泛型类

class GenericNumber {
    zeroValue: T;
    add: (x: T, y: T) => T;
}

let myGenericNumber = new GenericNumber();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };

泛型约束

我们想访问arg的length属性,但是编译器并不能证明每种类型都有length属性,所以就报错了。
创建一个包含 .length属性的接口,使用这个接口和extends关键字来实现约束:

interface Lengthwise {
    length: number;
}

function loggingIdentity(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((e).x + ',' + (e).y)); // 使用了类型断言
listenEvent(EventType.Mouse, <(e: Event) => void>((e: MouseEvent) => console.log(e.x + ',' + e.y))); // 这个看不懂

listenEvent(EventType.Mouse, (e: number) => console.log(e)); // 完全不一致所以会报错
```



你可能感兴趣的:(函数与泛型)