我们在前面 Day09 , 有简单讨论到 function,这篇就会来看一些更深入 function 的应用。
最简单定义 function 的用法:
function greeter(fn: (a: string) => void) {
fn("Hello, World");
}
function printToConsole(s: string) {
console.log(s);
}
greeter(printToConsole); //Hello, World
(a: string) => void
表示这个function带入的一个命名为 a 的参数,这个参数的型别为字串, 且此 funtion 没有 return 值。
特别注意一定要有参数命名,如(a: string)
。如果这样没命名, 这样写 (string) => void
就会表示这个参数命名为string, 型别是 any
。
此外, type 及 interface 也能定义 function , 可参考 Day15 这篇。
其实这个我一开始真的看不懂,感谢google大神让我找到实现官网例子的方法,大概了解了,下面也来实作一下。
在 JavaScript 中, function 是可以增加属性的(其实我不知道欸,好像没有试过对 function 增加属性)。於是想来证明是否真的可以,写了小例子,还真的可以增加属性:
const jsFunc = () => {
return "this's a function";
}
jsFunc.prop = "this's a prop";
jsFunc.desc = "this's a desc";
console.log(jsFunc); //[Function: func] { prop: "this's a prop", desc: "this's a desc" }
但在 TypeScript 中 type expression 是不允许对 function 新增属性的,於是我们可以在 object type 写一个 call signatures, 如下 DescribableFunction
。特别注意跟一般 function 不同的是返回型别是使用:
, 不是使用 =>
。
//新增 call signatures
type DescribableFunction = {
description: string;
(someArg: number): boolean; //这边特别注意我们使用:非 =>
};
function doSomething(fn: DescribableFunction) {
console.log(fn.description + " returned " + fn(6));
}
//回传boolean 如果大於5回传true
const func = (someArg: number): boolean => {
return someArg > 5;
};
//新增属性
func.description = "isNumber > 5";
doSomething(func); //isNumber > 5 returned true
一般我们使用 new 来建立新 object, 就称为 constructors 。
type SomeConstructor = {
new (s: string): SomeObject;
};
function fn(ctor: SomeConstructor) {
return new ctor("hello");
}
虽然在 JavaScript 中没有被带入的函式参数会是 undefined 且可以正常运作,但在 TypeScript 中,函式的参数预设都是必填的,没填的话 compiler 会直接喷错。
跟之前在介绍 object 型别可选属性一样,参数也可以选填,在参数後面使用?
。
// firstName 是必填,lastName 则可以选填
const getName = (firstName: string, lastName?: string) => {
return lastName ? `${firstName} ${lastName}` : firstName;
}
⚠️ 特别注意的是optional parameter 一定只能放在 required parameter 的後面。
⚠️ 官网也有特别提醒在 callback 的时候也尽量不要使用 optional parameter, 可能会发生这种错误。
const getName = (firstName: string, lastName = "Chen") => {
return `${firstName} ${lastName}`;
}
console.log(getName("Tom")); //Tom Chen
如果要使用预设值,在呼叫该函式的时候要使用undefined
。
const getName = (firstName = "Tom", lastName: string) => {
return `${firstName} ${lastName}`;
}
console.log(getName(undefined, "Chen")); //Tom Chen
想新增无限组参数,可使用剩余参数关键字 ...
function multiply(n: number, ...m: number[]) {
return m.map((x) => n * x);
}
const a = multiply(10, 1, 2, 3, 4);
console.log(a); //[10, 20, 30, 40]
const getName = (firstName: string, ...rest: string[]) => {
return `${firstName} ${rest.join(' ')}`;
}
const names = getName('Tom', 'Jerry', 'Chen');
console.log(names);
虽然可以用 push 的方式新增剩余参数是没问题:
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
arr1.push(...arr2);
console.log(arr1); // [1, 2, 3, 4, 5, 6]
但在 TypeScript , 但在一些使用上会有问题:
args
会被 inferred 型别为 number[]
, 不是特定两个数字。
// Inferred type is number[] -- "an array with zero or more numbers",
// not specifically two numbers
const args = [8, 5];
// error
const angle = Math.atan2(...args);
Math.atan2 是什麽 可参考这里。
我们可以把阵列直接当成 Tuple 使用,可以在定义阵列是加上 as const
,如此它就是会是一个值固定的 readonly array,这样就没问题了。如果没加上 as const
的话,则会是number[]
:
// Inferred as 2-length tuple
const args = [8, 5] as const;
// ok
const angle = Math.atan2(...args);
下一篇来笔记 Function Overloads 函式超载 ,第一次知道有这种功能, 觉得很cool。
https://zhuanlan.zhihu.com/p/266823134
https://stackoverflow.com/questions/66874130/how-to-properly-use-functions-construct-signatures-in-typescript
https://basarat.gitbook.io/typescript/type-system/type-inference
https://pjchender.dev/typescript/ts-functions/#%E9%81%B8%E5%A1%AB%E6%80%A7%E7%9A%84%E5%8F%83%E6%95%B8%E8%88%87%E5%8F%83%E6%95%B8%E9%A0%90%E8%A8%AD%E5%80%BC
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Math/atan2
https://pjchender.dev/typescript/ts-basic-types/
<<: [ Raspberry Pi ] Compute module 4 eMMC 烧录流程 ((CM4))
这篇来说剩下的重要功能 先来写删除的部分 就叫做removeTodo吧 加在a连结上,一样需要回传t...
Promise Promise.all():等待里面的都完成才回传,因为是全部完成,所以会是阵列,失...
如标题,这篇想和大家聊聊如何用SQL的语法做资料库的查询 请注意,SQL的函数皆为「全大写的英文字母...
本篇是看 Concurrency is not Parallelism 的心得 Concurrenc...
一样先上进度log: + exec /bin/busybox switch_root /sysroo...