docs: finish chapter function

This commit is contained in:
ruanyf
2023-07-17 22:21:48 +08:00
parent df8d21f2c5
commit 5edc67bc8d
3 changed files with 45 additions and 45 deletions

View File

@@ -71,7 +71,7 @@ f = function (y:number) {
上面示例中,函数类型里面的参数名为`x`,实际的函数定义里面,参数名为`y`,两者并不相同。
如果有多个变量被赋值为同一种类型的函数,写法二用起来就很麻烦。因此,往往用`type`命令为函数类型定义一个别名,便于指定给其他变量。
如果函数的类型定义很冗长,或者多个函数使用同一种类型,写法二用起来就很麻烦。因此,往往用`type`命令为函数类型定义一个别名,便于指定给其他变量。
```typescript
type MyFunc = (txt:string) => void;
@@ -83,7 +83,7 @@ const hello:MyFunc = function (txt) {
上面示例中,`type`命令为函数类型定义了一个别名`MyFunc`,后面使用就很方便,变量可以指定为这个类型。
变量所赋值的函数的参数个数,可以少于指定类型,但是不能多于指定类型,即这种情况下,TypeScript 允许省略参数。
函数的实际参数个数,可以少于类型指定的参数个数,但是不能多于,即 TypeScript 允许省略参数。
```typescript
let myFunc:
@@ -96,9 +96,9 @@ myFunc = (
) => a + b + c; // 报错
```
上面示例中,变量`myFunc`的类型只能接受两个参数,如果被赋值只有一个参数的函数,并不报错。但是,被赋值为有三个参数的函数,就会报错。
上面示例中,变量`myFunc`的类型只能接受两个参数,如果被赋值只有一个参数的函数,并不报错。但是,被赋值为有三个参数的函数,就会报错。
这是因为 JavaScript 函数在声明时往往有多余的参数,实际使用时可以只传入一部分参数。比如,数组的`forEach()`方法的参数是一个函数,该函数默认有三个参数`(item, index, array) => void`,实际上往往只使用第一个参数`(item) => any`。因此TypeScript 允许参数较少的函数,兼容于参数较多的函数。
这是因为 JavaScript 函数在声明时往往有多余的参数,实际使用时可以只传入一部分参数。比如,数组的`forEach()`方法的参数是一个函数,该函数默认有三个参数`(item, index, array) => void`,实际上往往只使用第一个参数`(item) => void`。因此TypeScript 允许函数传入的参数不足
```typescript
let x = (a:number) => 0;
@@ -110,7 +110,7 @@ x = y; // 报错
上面示例中,函数`x`只有一个参数,函数`y`有两个参数,`x`可以赋值给`y`,反过来就不行。
如果一个变量要套用另一个函数类型,有一个小技巧,就是使用`typeof`运算符。
如果一个变量要套用另一个函数类型,有一个小技巧,就是使用`typeof`运算符。
```typescript
function add(
@@ -159,7 +159,7 @@ add = function (x, y) {
function f(x:number) {
console.log(x);
}
f.version = '1.0';
```
@@ -221,7 +221,7 @@ function greet(
):void {
fn('world');
}
```
```
上面示例中,函数`greet()`的参数`fn`是一个函数,类型就用箭头函数表示。这时,`fn`的返回值类型要写在箭头右侧,而不是写在参数列表的圆括号后面。
@@ -266,13 +266,13 @@ f(); // OK
f(10); // OK
```
上面示例中,虽然参数`x`后面有问号,表示该参数可以省略,不一定需要给出
上面示例中,虽然参数`x`后面有问号,表示该参数可以省略。
参数名带有问号,表示该参数的类型实际上是`原始类型|undefined`,它有可能为`undefined`。比如,上例的`x`虽然类型声明为`number`,但是实际上是`number|undefined`
```typescript
function f(x?:number) {
return x;
function f(x?:number) {
return x;
}
f(undefined) // 正确
@@ -301,7 +301,7 @@ let myFunc:
上面示例中,可选参数在必选参数前面,就报错了。
如果前部参数有可能为空,这时只能显注明该参数类型可能为`undefined`
如果前部参数有可能为空,这时只能显注明该参数类型可能为`undefined`
```typescript
let myFunc:
@@ -361,7 +361,7 @@ function createPoint(
```typescript
// 报错
function f(x?: number = 0) {
// ...
// ...
}
```
@@ -401,7 +401,7 @@ function f(
) {
// ...
}
function sum(
{ a, b, c }: {
a: number;
@@ -532,10 +532,10 @@ function f():void {
}
```
如果打开了`--strictNullChecks`编译选项,那么 void 类型只允许返回`undefined`。如果返回`null`,就会报错。这是因为 JavaScript 规定,如果函数没有返回值,就等同于返回`undefined`
如果打开了`strictNullChecks`编译选项,那么 void 类型只允许返回`undefined`。如果返回`null`,就会报错。这是因为 JavaScript 规定,如果函数没有返回值,就等同于返回`undefined`
```typescript
// --strictNullChecks=true
// 打开编译选项 strictNullChecks
function f():void {
return undefined; // 正确
@@ -550,7 +550,7 @@ function f():void {
```typescript
type voidFunc = () => void;
const f:voidFunc = () => {
return 123;
};
@@ -606,7 +606,7 @@ const f3 = function ():void {
```typescript
let foo:void = undefined;
// 没有打开 --strictNullChecks 的情况下
// 没有打开 strictNullChecks 的情况下
let bar:void = null;
```
@@ -763,10 +763,7 @@ function add(
):number|any[] {
if (typeof x === 'number' && typeof y === 'number') {
return x + y;
} else
if (Array.isArray(x) && Array.isArray(y)) {
} else if (Array.isArray(x) && Array.isArray(y)) {
return [...x, ...y];
}
@@ -801,7 +798,7 @@ function f(x:string): 0|1;
function f(x:any):any {
// ...
}
const a:0|1 = f('hi'); // 报错
```
@@ -827,7 +824,7 @@ class StringBuilder {
}
```
上面示例中,方法`add()`也使用了函数重载。
上面示例中,方法`add()`也使用了函数重载。
函数重载也可以用来精确描述函数参数与返回值之间的对应关系。
@@ -891,7 +888,25 @@ const d = new Date();
上面示例中,`date()`就是一个构造函数,使用`new`命令调用,返回 Date 对象的实例。
构造函数的类型声明,采用对象形式
构造函数的类型写法,就是在参数列表前面加上`new`命令
```typescript
class Animal {
numLegs:number = 4;
}
type AnimalConstructor = new () => Animal;
function create(c:AnimalConstructor):Animal {
return new c();
}
const a = create(Animal);
```
上面示例中,类型`AnimalConstructor`就是一个构造函数,而函数`create()`需要传入一个构造函数。在 JavaScript 中class本质上是构造函数所以`Animal`这个类可以传入`create()`
构造函数还有另一种类型写法,就是采用对象形式。
```typescript
type F = {
@@ -912,20 +927,3 @@ type F = {
上面示例中F 既可以当作普通函数执行,也可以当作构造函数使用。
下面是构造函数的一个例子。
```typescript
class Animal {
numLegs: number = 4;
}
function create(c:new () => Animal):Animal {
return new c();
}
const a = create(Animal);
```
上面示例中,函数`create()`的参数`c`是一个构造函数。在 JavaScript 中class本质上是构造函数所以可以传入`create()`
不过,构造函数在 TypeScript 里面实际上只能用类class的形式来实现详见《Class》一章。

View File

@@ -27,7 +27,7 @@ x === y // false
```typescript
// 正确
const x:unique symbol = Symbol();
const x:unique symbol = Symbol();
// 报错
let y:unique symbol = Symbol();
@@ -38,12 +38,12 @@ let y:unique symbol = Symbol();
`const`命令为变量赋值 Symbol 值时,变量类型默认就是`unique symbol`,所以类型可以省略不写。
```typescript
const x:unique symbol = Symbol();
const x:unique symbol = Symbol();
// 等同于
const x = Symbol();
```
每个声明为`unique symbol`类型的变量,它们的值都是不一样的,其实属于两个类型。
每个声明为`unique symbol`类型的变量,它们的值都是不一样的,其实属于两个类型。
```typescript
const a:unique symbol = Symbol();
@@ -85,7 +85,7 @@ const b:typeof a = a; // 正确
```typescript
const a:unique symbol = Symbol.for('foo');
const b:unique symbol = Symbol.for('foo');
const b:unique symbol = Symbol.for('foo');
```
上面示例中,变量`a``b`是两个不同的值类型,但是它们的值其实是相等的。
@@ -161,3 +161,4 @@ const x = Symbol();
// 类型为 symbol
let y = x;
```