09 - TS 关于函数的补充
函数的补充
构造函数的表达
/* 定义构造函数类型 其中 'new' 表示构造函数 s: int 是构造函数的参数类型 返回值类型为 String */ type SomeConstructor = { new (s: int): String } /* 函数 fn 接收一个构造函数作为参数,并使用该构造函数创建一个新对象。 */ function fn(ctor: SomeConstructor) { return new ctor("hello"); } const str = fn(String); console.log(str); // 输出: hello
泛型函数
/* 泛型函数定义,返回数组的第一个元素。 Type 是一个泛型参数,代表任意类型。 */ function firstElement(arr: Type[]): Type { return arr[0]; } /* 非泛型版本,使用 'any' 类型。这种写法失去了类型的保证。 */ function firstElement(arr: any): any { return arr[0]; }
关于推导
/* 使用泛型和推导来映射数组的值。 Input 和 Output 都是泛型参数,代表输入和输出的类型。 */ function map<Input, Output>( arr: Input[], func: (arg: Input) => Output): Output[] { return arr.map(func); } const parsed = map(["1", "2", "3"], (n) => parseInt(n)); // 输出: [1,2,3]
泛型约束
/* 使用泛型约束确保对象具有 length 属性。 但此函数的返回类型可能与输入的类型不符。 */ function minimumLength( obj: Type, minimum: number ): Type { if (obj.length >= minimum) { return obj; } else { return { length: minimum }; // 错误: Type '{ length: number; }' is not assignable to type 'Type'. } }
手动指定类型
/* 组合两个数组,但由于类型不匹配会报错。 */ function combine(arr1: Type[], arr2: Type[]): Type[] { return arr1.concat(arr2); } /* 手动指定泛型参数来解决类型不匹配的问题。 */ const arr = combine([1, 2, 3], ["hello"]);
函数的重载(overloading)
/* 定义了一个加法函数,但由于不确定输入的类型,所以使用函数重载来约束可能的输入和输出类型。 */ function isSet(x: any): x is Set { return x instanceof Set; } function add(a: number, b: number): number; function add(a: string, b: string): string; function add(a: Set, b: Set): Set; function add(a: T, b: T): T { if(isSet(a) && isSet(b)){ return new Set([...a, ...b]) as any; } return (a as any) + (b as any); } const a = new Set(["apple", "redhat"]); const b = new Set(["google", "ms"]); console.log(add(a, b)); console.log(add(1, 2)); console.log(add("a", "k"));
THIS
/* 在接口中定义一个方法,然后在函数中使用 'this' 来约束函数的调用者。 */ interface DB { exec(sql: string): any; } function runSql(this: DB, sql: string) { this.exec(sql); } runSql.bind(new DB()).("select * from user");
void vs unknown
/* 对于不返回任何值的函数,使用 'void' 类型。 对于可能返回任何类型的函数,使用 'unknown' 类型。 */ function safeParse(s: string): unknown { return JSON.parse(s); } function fail(msg: string): never { throw new Error(msg); }
rest params
/* 使用剩余参数来定义一个接受不定数量参数的函数。 */ function multiply(n: number, ...m: number[]) { return m.map((x) => n * x); } const a = multiply(10, 1, 2, 3, 4); // 输出: [10, 20, 30, 40]
总结
泛型帮助我们在编写时保持代码的灵活性,同时在编译时获得强类型检查的能力。