Skip to content

可选参数

JavaScript中的函数经常需要一个可变数量的参数。例如, number 的 toFixed 方法需要一个可选的数字计数。

typescript
function f(n: number) { 
  console.log(n.toFixed()); // 0 个参数 
  console.log(n.toFixed(3)); // 1 个参数 
}

我们可以在TypeScript中通过将参数用 ? 标记:

typescript
function f(x?: number) { 
  // ... 
}
f(); // 正确 
f(10); // 正确

虽然参数被指定为 number 类型,但 x 参数实际上将具有 number | undefined 类型,因为在 JavaScript 中未指定的参数会得到 undefined 的值。

你也可以提供一个参数默认值。

typescript
function f(x = 10) { 
  // ... 
}

现在在 f 的主体中, x 将具有 number 类型,因为任何 undefined 的参数将被替换为 10 。请注意,当一个参数是可选的,调用者总是可以传递未定义的参数,因为这只是模拟一个 "丢失 "的参数:

typescript
declare function f(x?: number): void; 

// 以下调用都是正确的 
f(); 
f(10); 
f(undefined);

回调中的可选参数

一旦你了解了可选参数和函数类型表达式,在编写调用回调的函数时就很容易犯以下错误:

typescript
function myForEach(arr: any[], callback: (arg: any, index?: number) => void) { 
  for (let i = 0; i < arr.length; i++) { 
    callback(arr[i], i); 
  } 
}

我们在写 index? 作为一个可选参数时,通常是想让这些调用都是合法的:

typescript
myForEach([1, 2, 3], (a) => console.log(a)); 
myForEach([1, 2, 3], (a, i) => console.log(a, i));

这实际上意味着回调可能会被调用,只有一个参数。换句话说,该函数定义说,实现可能是这样的:

typescript
function myForEach(arr: any[], callback: (arg: any, index?: number) => void) { 
  for (let i = 0; i < arr.length; i++) { 
    // 我现在不想提供索引 
    callback(arr[i]); 
  } 
}

反过来,TypeScript会强制执行这个意思,并发出实际上不可能的错误:

typescript
myForEach([1, 2, 3], (a, i) => { 
  console.log(i.toFixed()) 
})

在JavaScript中,如果你调用一个形参多于实参的函数,额外的参数会被简单地忽略。TypeScript的行为也是如此。参数较少的函数(相同的类型)总是可以取代参数较多的函数的位置。

当为回调写一个函数类型时,永远不要写一个可选参数,除非你打算在不传递该参数的情况下调用函数