Function type definition
TypeScript's function type definitions provide powerful tools for describing the input and output behavior of functions. Through type annotations and interfaces, parameters and return values can be precisely constrained, while advanced features like overloading and generics are also supported.
Basic Syntax of Function Types
Function types consist of parameter types and a return type, expressed using arrow syntax:
type MathOperation = (a: number, b: number) => number;
This type defines a function that takes two numeric parameters and returns a number. In practice:
const add: MathOperation = (x, y) => x + y;
const multiply: MathOperation = (x, y) => x * y;
Optional and Default Parameters
TypeScript allows defining optional parameters and parameters with default values:
type GreetFunction = (name: string, prefix?: string) => string;
const greet: GreetFunction = (name, prefix = 'Hello') => {
return `${prefix}, ${name}!`;
};
console.log(greet('Alice')); // "Hello, Alice!"
console.log(greet('Bob', 'Hi')); // "Hi, Bob!"
Typing Rest Parameters
For handling variable numbers of arguments, rest parameter syntax can be used:
type SumNumbers = (...numbers: number[]) => number;
const sum: SumNumbers = (...nums) => {
return nums.reduce((acc, curr) => acc + curr, 0);
};
console.log(sum(1, 2, 3)); // 6
console.log(sum(10, 20)); // 30
Function Overloading
TypeScript supports function overloading, allowing multiple type definitions for the same function:
// Overload signatures
function reverse(str: string): string;
function reverse<T>(arr: T[]): T[];
// Implementation signature
function reverse(input: string | any[]): string | any[] {
if (typeof input === 'string') {
return input.split('').reverse().join('');
} else {
return input.slice().reverse();
}
}
console.log(reverse('TypeScript')); // "tpircSepyT"
console.log(reverse([1, 2, 3])); // [3, 2, 1]
Generic Functions
Generics enable functions to handle multiple types without losing type information:
type IdentityFunc<T> = (arg: T) => T;
const identity: IdentityFunc<number> = (x) => x;
const stringIdentity: IdentityFunc<string> = (s) => s;
function firstElement<T>(arr: T[]): T | undefined {
return arr[0];
}
console.log(firstElement([1, 2, 3])); // 1
console.log(firstElement(['a', 'b', 'c'])); // "a"
Higher-Order Function Types
Handling functions as parameters or return values:
type MapperFunc<T, U> = (item: T) => U;
type ArrayMapper<T, U> = (arr: T[], mapper: MapperFunc<T, U>) => U[];
const numberToStringMapper: MapperFunc<number, string> = (n) => n.toString();
const mapArray: ArrayMapper<number, string> = (arr, mapper) => arr.map(mapper);
console.log(mapArray([1, 2, 3], numberToStringMapper)); // ["1", "2", "3"]
Constructor Types
Using the new
keyword to define constructor types:
interface Point {
x: number;
y: number;
}
type PointConstructor = new (x: number, y: number) => Point;
class Point2D implements Point {
constructor(public x: number, public y: number) {}
}
function createPoint(ctor: PointConstructor, x: number, y: number): Point {
return new ctor(x, y);
}
const point = createPoint(Point2D, 10, 20);
console.log(point); // Point2D { x: 10, y: 20 }
Async Function Types
Handling Promise return values:
type FetchData = (url: string) => Promise<any>;
const fetchUser: FetchData = async (url) => {
const response = await fetch(url);
return response.json();
};
fetchUser('https://api.example.com/users/1')
.then(data => console.log(data));
Combining Function Types with Interfaces
Interfaces can fully describe function types:
interface SearchFunc {
(source: string, subString: string): boolean;
}
const mySearch: SearchFunc = (src, sub) => {
return src.includes(sub);
};
console.log(mySearch('TypeScript', 'Script')); // true
Type Inference and Contextual Typing
TypeScript can infer function types based on context:
const names = ['Alice', 'Bob', 'Charlie'];
// Infers item type as string
names.map(item => item.toUpperCase());
// Explicit typing
names.map((item: string) => item.length);
Complex Function Type Examples
Combining multiple features into complex type definitions:
type EventHandler<E extends Event> = (event: E) => void;
type EventMap = {
click: MouseEvent;
keydown: KeyboardEvent;
};
function addEventListener<K extends keyof EventMap>(
type: K,
handler: EventHandler<EventMap[K]>,
options?: boolean | AddEventListenerOptions
): void {
// Actual implementation
}
addEventListener('click', (e) => {
console.log(`Clicked at (${e.clientX}, ${e.clientY})`);
});
addEventListener('keydown', (e) => {
console.log(`Key pressed: ${e.key}`);
});
Function Type Compatibility
TypeScript uses a structural type system with function type compatibility rules:
type Handler = (a: number, b: number) => void;
// Fewer parameters are compatible
const handler1: Handler = (a) => console.log(a);
// Parameter types are compatible
const handler2: Handler = (a: number, b: number, c?: string) => console.log(a + b);
// Return type compatibility
const handler3: Handler = () => {};
Advanced Patterns for Function Types
Using conditional and mapped types to create flexible function types:
type Promisify<T> = T extends (...args: infer A) => infer R
? (...args: A) => Promise<R>
: T;
function promisify<F extends (...args: any[]) => any>(fn: F): Promisify<F> {
return ((...args: Parameters<F>) => {
return new Promise((resolve) => {
resolve(fn(...args));
});
}) as Promisify<F>;
}
const syncAdd = (a: number, b: number): number => a + b;
const asyncAdd = promisify(syncAdd);
asyncAdd(1, 2).then(result => console.log(result)); // 3
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn