先来个最简单的例子
先来看一个JavaScript箭头函数
// JavaScript
const add = (x, y) => x + y;
再来看TypeScript 中它是怎样的,TypeScript 允许为箭头函数提供参数和返回类型的类型注解。
// TypeScript
const add: (x: number, y: number) => number = (x, y) => x + y;
是不是乍一看很懵,哪里是函数,哪里又是类型注解。
仔细研究还是能看出来:
这里的类型注解是(x: number, y: number) => number
这一部分,表示函数接受两个number类型的变量,并返回一个number类型的值;
这里的函数是(x, y) => x + y
这一部分。
再来点例子试一试
例子一
export const enableBetterErrorHandlingAndLogging: (
connection: Connection
) => void = connection => {
const connectionConsole = useConnectionConsole(connection, { trace: false });
console.log = connectionConsole('log');
console.info = connectionConsole('info');
console.error = connectionConsole('error');
process.on('uncaughtException', handleError);
process.on('unhandledRejection', handleError);
};
这里的类型注解是( connection: Connection ) => void
表示该函数接受一个 connection参数,然后没有返回值
这样试了一下,是不是觉得也没啥,那么假如箭头函数的返回值是一个箭头函数呢,看看例子二吧。
例子二
export const autoRenameTag: (
documents: TextDocuments<TextDocument>
) => (params: Params) => Promise<Result[]> =
(documents) =>
async ({ textDocument, tags }) => {
await new Promise((r) => setTimeout(r, 20));
const document = documents.get(textDocument.uri);
if (!document) {
return NULL_AUTO_RENAME_TAG_RESULT;
}
if (textDocument.version !== document.version) {
return NULL_AUTO_RENAME_TAG_RESULT;
}
const text = document.getText();
const results: Result[] = tags
.map((tag) => {
const result = doAutoRenameTag(
text,
tag.offset,
tag.word,
tag.oldWord,
document.languageId
);
if (!result) {
return result;
}
(result as any).originalOffset = tag.offset;
(result as any).originalWord = tag.word;
return result as Result;
})
.filter(Boolean) as Result[];
return results;
};
这里的类型是( documents: TextDocuments<TextDocument> ) => (params: Params) => Promise<Result[]>
表示该函数接受一个 documents 参数,然后返回一个函数,返回的函数接受一个 params 参数,返回一个 Promise,解析为 Result[] 数组。是不是看到这个函数有点懵了
阅读技巧
其实总结下有个非常简单的阅读小技巧,就是看=
的位置,前面的都是类型,后面的是函数
再来看下更套娃的
如果函数返回函数,返回函数再返回函数,再返回函数再再返回函数,则箭头函数则需要无限套娃定义ts类型,比如下方代码
这里的类型是( connection: Connection, { trace }: { trace?: boolean } ) => (method: 'log' | 'info' | 'error') => (...args: any[]) => void
使用小技巧,快速找到=号位置,前面的都是类型,后面的是函数
const useConnectionConsole: (
connection: Connection,
{ trace }: { trace?: boolean }
) => (method: 'log' | 'info' | 'error') => (...args: any[]) => void =
(connection, { trace = false } = {}) =>
method =>
(...args) => {
if (trace) {
const stack = new Error().stack || '';
let file = stack.split('\n')[2];
file = file.slice(file.indexOf('at') + 'at'.length, -1);
const match = file.match(/(.*):(\d+):(\d+)$/);
if (match) {
const [_, path, line, column] = match;
connection.console[method]('at ' + path + ':' + line);
}
}
const stringify: (arg: any) => string = arg => {
if (arg && arg.toString) {
if (arg.toString() === '[object Promise]') {
return JSON.stringify(arg);
}
if (arg.toString() === '[object Object]') {
return JSON.stringify(arg);
}
return arg;
}
return JSON.stringify(arg);
};
connection.console[method](args.map(stringify).join(''));
};